372 {
374
375 constexpr bool debug =
false;
376
377 constexpr int numNodes = 4;
378 constexpr int numEdges = 6;
379 constexpr int refinementLevels = 6;
380
381 auto &m_field = fe_raw_ptr->
mField;
382 auto fe_ptr = static_cast<Fe *>(fe_raw_ptr);
383 auto fe_handle = fe_ptr->getFEEntityHandle();
384
385 auto set_base_quadrature = [&]() {
387 int rule = 2 * order_data + 1;
391 "wrong dimension");
392 }
396 }
398 auto &gauss_pts = fe_ptr->gaussPts;
399 gauss_pts.resize(4, nb_gauss_pts, false);
400 cblas_dcopy(nb_gauss_pts, &
QUAD_3D_TABLE[rule]->points[1], 4,
401 &gauss_pts(0, 0), 1);
402 cblas_dcopy(nb_gauss_pts, &
QUAD_3D_TABLE[rule]->points[2], 4,
403 &gauss_pts(1, 0), 1);
404 cblas_dcopy(nb_gauss_pts, &
QUAD_3D_TABLE[rule]->points[3], 4,
405 &gauss_pts(2, 0), 1);
407 &gauss_pts(3, 0), 1);
408 auto &data = fe_ptr->dataOnElement[
H1];
409 data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).resize(nb_gauss_pts, 4,
410 false);
411 double *shape_ptr =
412 &*data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).data().begin();
413 cblas_dcopy(4 * nb_gauss_pts,
QUAD_3D_TABLE[rule]->points, 1, shape_ptr,
414 1);
415 } else {
418 }
420 };
421
422 CHKERR set_base_quadrature();
423
425
426 auto get_singular_nodes = [&]() {
427 int num_nodes;
429 CHKERR m_field.get_moab().get_connectivity(fe_handle, conn, num_nodes,
430 true);
431 std::bitset<numNodes> singular_nodes;
432 for (auto nn = 0; nn != numNodes; ++nn) {
434 singular_nodes.set(nn);
435 } else {
436 singular_nodes.reset(nn);
437 }
438 }
439 return singular_nodes;
440 };
441
442 auto get_singular_edges = [&]() {
443 std::bitset<numEdges> singular_edges;
444 for (int ee = 0; ee != numEdges; ee++) {
446 CHKERR m_field.get_moab().side_element(fe_handle, 1, ee, edge);
448 singular_edges.set(ee);
449 } else {
450 singular_edges.reset(ee);
451 }
452 }
453 return singular_edges;
454 };
455
456 auto set_gauss_pts = [&](auto &ref_gauss_pts) {
458 fe_ptr->gaussPts.swap(ref_gauss_pts);
459 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
460 auto &data = fe_ptr->dataOnElement[
H1];
461 data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).resize(nb_gauss_pts, 4);
462 double *shape_ptr =
463 &*data->dataOnEntities[MBVERTEX][0].getN(
NOBASE).data().begin();
465 &fe_ptr->gaussPts(1, 0), &fe_ptr->gaussPts(2, 0),
466 nb_gauss_pts);
468 };
469
470 auto singular_nodes = get_singular_nodes();
471 if (singular_nodes.count()) {
472 auto it_map_ref_coords =
mapRefCoords.find(singular_nodes.to_ulong());
474 CHKERR set_gauss_pts(it_map_ref_coords->second);
476 } else {
477
478 auto refine_quadrature = [&]() {
480
481 const int max_level = refinementLevels;
483
484 moab::Core moab_ref;
485 double base_coords[] = {0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1};
487 for (int nn = 0; nn != 4; nn++)
488 CHKERR moab_ref.create_vertex(&base_coords[3 * nn], nodes[nn]);
489 CHKERR moab_ref.create_element(MBTET, nodes, 4, tet);
492 {
493 Range tets(tet, tet);
496 tets, 1, true, edges, moab::Interface::UNION);
499 }
500
501 Range nodes_at_front;
502 for (int nn = 0; nn != numNodes; nn++) {
503 if (singular_nodes[nn]) {
505 CHKERR moab_ref.side_element(tet, 0, nn, ent);
506 nodes_at_front.insert(ent);
507 }
508 }
509
510 auto singular_edges = get_singular_edges();
511
513 CHKERR moab_ref.create_meshset(MESHSET_SET, meshset);
514 for (int ee = 0; ee != numEdges; ee++) {
515 if (singular_edges[ee]) {
517 CHKERR moab_ref.side_element(tet, 1, ee, ent);
518 CHKERR moab_ref.add_entities(meshset, &ent, 1);
519 }
520 }
521
522
524 for (int ll = 0; ll != max_level; ll++) {
527 ->getEntitiesByTypeAndRefLevel(
BitRefLevel().set(ll),
529 edges);
531 CHKERR moab_ref.get_adjacencies(
532 nodes_at_front, 1, true, ref_edges, moab::Interface::UNION);
533 ref_edges = intersect(ref_edges, edges);
535 CHKERR moab_ref.get_entities_by_type(meshset, MBEDGE, ents,
true);
536 ref_edges = intersect(ref_edges, ents);
539 ->getEntitiesByTypeAndRefLevel(
541 CHKERR m_ref->addVerticesInTheMiddleOfEdges(
545 ->updateMeshsetByEntitiesChildren(meshset,
547 meshset, MBEDGE, true);
548 }
549
550
553 ->getEntitiesByTypeAndRefLevel(
BitRefLevel().set(max_level),
555 tets);
556
559 }
560
562 int tt = 0;
563 for (Range::iterator tit = tets.begin(); tit != tets.end();
564 tit++, tt++) {
565 int num_nodes;
567 CHKERR moab_ref.get_connectivity(*tit, conn, num_nodes,
false);
568 CHKERR moab_ref.get_coords(conn, num_nodes, &ref_coords(tt, 0));
569 }
570
571 auto &data = fe_ptr->dataOnElement[
H1];
572 const size_t nb_gauss_pts = fe_ptr->gaussPts.size2();
573 MatrixDouble ref_gauss_pts(4, nb_gauss_pts * ref_coords.size1());
575 data->dataOnEntities[MBVERTEX][0].getN(
NOBASE);
576 int gg = 0;
577 for (size_t tt = 0; tt != ref_coords.size1(); tt++) {
578 double *tet_coords = &ref_coords(tt, 0);
580 det *= 6;
581 for (size_t ggg = 0; ggg != nb_gauss_pts; ++ggg, ++gg) {
582 for (
int dd = 0;
dd != 3;
dd++) {
583 ref_gauss_pts(dd, gg) =
584 shape_n(ggg, 0) * tet_coords[3 * 0 +
dd] +
585 shape_n(ggg, 1) * tet_coords[3 * 1 +
dd] +
586 shape_n(ggg, 2) * tet_coords[3 * 2 +
dd] +
587 shape_n(ggg, 3) * tet_coords[3 * 3 +
dd];
588 }
589 ref_gauss_pts(3, gg) = fe_ptr->gaussPts(3, ggg) * det;
590 }
591 }
592
593 mapRefCoords[singular_nodes.to_ulong()].swap(ref_gauss_pts);
595
596
599
600 TetPolynomialBase::switchCacheBaseOff<HDIV>({fe_raw_ptr});
601 TetPolynomialBase::switchCacheBaseOn<HDIV>({fe_raw_ptr});
602
604 };
605
606 CHKERR refine_quadrature();
607 }
608 }
609 }
610
612 }
#define MoFEMFunctionReturnHot(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define MoFEMFunctionBegin
First executable line of each MoFEM function, used for error handling. Final line of MoFEM functions ...
@ MOFEM_DATA_INCONSISTENCY
#define MoFEMFunctionReturn(a)
Last executable line of each PETSc function used for error handling. Replaces return()
#define CHKERR
Inline error check.
constexpr int order
Order displacement.
const Tensor2_symmetric_Expr< const ddTensor0< T, Dim, i, j >, typename promote< T, double >::V, Dim, i, j > dd(const Tensor0< T * > &a, const Index< i, Dim > index1, const Index< j, Dim > index2, const Tensor1< int, Dim > &d_ijk, const Tensor1< double, Dim > &d_xyz)
std::bitset< BITREFLEVEL_SIZE > BitRefLevel
Bit structure attached to each entity identifying to what mesh entity is attached.
#define QUAD_3D_TABLE_SIZE
static QUAD *const QUAD_3D_TABLE[]
static PetscBool setSingularity
static std::map< long int, MatrixDouble > mapRefCoords
virtual moab::Interface & get_moab()=0
Deprecated interface functions.
Mesh refinement interface.
MoFEMErrorCode getInterface(IFACE *&iface) const
Get interface reference to pointer of interface.