34 _max_mesh_elem_id (0),
35 _max_mesh_node_id (0),
40 _if_elem_on_positive_phi (false),
41 _if_elem_on_negative_phi (false),
43 _node_num_on_boundary (0),
44 _edge_num_on_boundary (0){
163 std::vector<const libMesh::Elem*>::const_iterator
169 v0 =
_elem->volume();
171 for ( ; it != end; it++)
172 v += (*it)->volume();
183 std::map<const libMesh::Node*, std::pair<Real, bool> >::const_iterator
187 libmesh_assert(it != end);
188 return it->second.first;
221 std::vector<libMesh::Elem*>::iterator
225 for ( ; e_it != e_end; e_it++)
229 std::vector<libMesh::Node*>::iterator
233 for ( ; n_it != n_end; n_it++)
246 const libMesh::Elem& e,
248 unsigned int max_elem_id,
249 unsigned int max_node_id) {
253 libmesh_assert_equal_to(e.dim(), 2);
266 case libMesh::QUAD9: {
268 std::unique_ptr<libMesh::Elem>
282 std::unique_ptr<libMesh::Elem>
285 std::unique_ptr<libMesh::Elem>
289 case libMesh::QUAD9: {
291 first_order_elem.reset(libMesh::Elem::build(libMesh::QUAD4).release());
293 for (
unsigned int i=0; i<4; i++)
294 first_order_elem->set_node(i) =
const_cast<libMesh::Node*
>(e.node_ptr(i));
296 first_order_elem->set_id() = e.id();
305 return first_order_elem;
314 const libMesh::Elem& e,
319 libmesh_assert_equal_to(e.dim(), 2);
320 libmesh_assert(
_elem);
334 n_node_intersection = 0;
342 on_level_set =
false;
345 for (
unsigned int i=0; i<
_elem->n_nodes(); i++) {
347 const libMesh::Node& n =
_elem->node_ref(i);
349 on_level_set = fabs(val) <=
_tol;
355 if (i < e.n_nodes() && on_level_set) {
357 n_node_intersection++;
359 min_val = (min_val > val)? val : min_val;
360 max_val = (max_val < val)? val : max_val;
370 if (min_val >
_tol) {
380 else if (max_val < -
_tol) {
406 val1 = std::fabs(min_val)<
_tol ? 0.: min_val,
407 val2 = std::fabs(max_val)<
_tol ? 0.: max_val;
409 sign_change = (val1*val2 < 0.);
410 if (n_node_intersection == 1 &&
420 if (min_val <=
_tol &&
426 libmesh_assert_greater(max_val,
_tol);
430 std::vector<std::pair<libMesh::Point, libMesh::Point> >
442 for (
unsigned int i=0; i<e.n_sides(); i++) {
444 std::unique_ptr<const libMesh::Elem>
445 s(e.side_ptr(i).release());
448 n_nodes_on_level_set = 0;
450 for (
unsigned int j=0; j<s->n_nodes(); j++)
453 if (n_nodes_on_level_set == s->n_nodes()) {
467 else if (min_val <
_tol)
470 std::vector<std::pair<libMesh::Point, libMesh::Point> >
494 libmesh_error_msg(
"level-set intersections for elem type not handled.");
514 for (
unsigned int i=0; i<
_new_elems.size(); i++) {
516 _new_elems[i]->subdomain_id() = e.subdomain_id();
526 const std::vector<const libMesh::Elem*>&
534 const std::vector<const libMesh::Elem*>&
552 switch (
_elem->type()) {
563 std::map<const libMesh::Node*, std::pair<Real, bool>>::const_iterator
567 for (
unsigned int i=0; i<n_corner_nodes; i++) {
569 const libMesh::Node* nd =
_elem->node_ptr(i);
573 libmesh_assert(it != end);
575 if (it->second.first < 0.)
576 nodes.insert(it->first);
586 std::map<const libMesh::Elem*, int>::const_iterator it;
591 return it->second >= 0;
600 std::map<const libMesh::Elem*, int>::const_iterator it;
604 libmesh_assert(it->second >= 0);
612 (
const libMesh::Elem& e,
613 std::vector<std::pair<libMesh::Point, libMesh::Point> >& side_nondim_points,
614 std::map<const libMesh::Node*, libMesh::Point>& node_coord_map) {
618 case libMesh::QUAD4: {
623 side_nondim_points.resize(4);
625 side_nondim_points[0] =
626 std::pair<libMesh::Point, libMesh::Point>
627 (libMesh::Point(-1, -1, 0.),
628 libMesh::Point(+1, -1, 0.));
629 side_nondim_points[1] =
630 std::pair<libMesh::Point, libMesh::Point>
631 (libMesh::Point(+1, -1, 0.),
632 libMesh::Point(+1, +1, 0.));
633 side_nondim_points[2] =
634 std::pair<libMesh::Point, libMesh::Point>
635 (libMesh::Point(+1, +1, 0.),
636 libMesh::Point(-1, +1, 0.));
637 side_nondim_points[3] =
638 std::pair<libMesh::Point, libMesh::Point>
639 (libMesh::Point(-1, +1, 0.),
640 libMesh::Point(-1, -1, 0.));
644 for (
unsigned int i=0; i<4; i++)
645 node_coord_map[e.node_ptr(i)] = side_nondim_points[i].first;
650 libmesh_assert(
false);
659 const libMesh::Elem& e,
661 const std::map<
const libMesh::Node*, std::pair<Real, bool> >&
664 libmesh_assert_equal_to(e.type(), libMesh::QUAD4);
667 std::vector<std::pair<libMesh::Point, libMesh::Point> >
674 std::vector<std::pair<bool, Real> >
675 side_intersection(n_nodes, std::pair<bool, Real>(
false, 0.));
677 node_intersection(n_nodes,
false);
679 std::map<const libMesh::Node*, std::pair<Real, bool> >::const_iterator
682 it_end = node_phi_vals.end();
689 for (
unsigned int i=0; i<n_nodes; i++) {
691 it0 = node_phi_vals.find(e.node_ptr(i));
692 libmesh_assert(it0 != it_end);
695 if (std::fabs(it0->second.first) <
_tol)
696 node_intersection[i] =
true;
700 it1 = node_phi_vals.find(e.node_ptr((i+1)%n_nodes));
701 libmesh_assert(it1 != it_end);
702 v0 = it0->second.first;
703 v1 = it1->second.first;
704 if (std::fabs(v0) >
_tol &&
705 std::fabs(v1) >
_tol &&
709 side_intersection[i] = std::pair<bool, Real>
727 std::vector<std::pair<bool, Real> >::const_iterator
728 it = side_intersection.begin(),
729 end = side_intersection.end();
731 for (; it != end; it++)
732 n_intersection += it->first;
737 std::vector<bool>::const_iterator
738 it = node_intersection.begin(),
739 end = node_intersection.end();
741 for (; it != end; it++)
742 n_intersection += *it;
764 switch (n_intersection) {
766 for (
unsigned int i=0; i<n_nodes; i++) {
768 if (side_intersection[i].first &&
769 side_intersection[(i+1)%n_nodes].first) {
775 else if (side_intersection[i].first &&
776 side_intersection[(i+2)%n_nodes].first) {
782 else if (node_intersection[i] &&
783 node_intersection[(i+2)%n_nodes]) {
789 else if (node_intersection[i] &&
790 side_intersection[(i+1)%n_nodes].first) {
796 else if (node_intersection[i] &&
797 side_intersection[(i+2)%n_nodes].first) {
810 for (
unsigned int i=0; i<n_nodes; i++) {
811 if (node_intersection[i] &&
812 side_intersection[(i+1)%n_nodes].first &&
813 side_intersection[(i+2)%n_nodes].first) {
827 if (side_intersection[0].first &&
828 side_intersection[1].first &&
829 side_intersection[2].first &&
830 side_intersection[3].first) {
849 phi(e.centroid(), t, mid_phi);
850 it0 = node_phi_vals.find(e.node_ptr(0));
851 v0 = it0->second.first;
853 if (mid_phi * v0 > 0.)
901 libmesh_assert_equal_to(
_new_nodes.size(), 0);
906 std::unique_ptr<const libMesh::Elem>
910 ref_side_node0_positive =
false;
931 xi_ref = side_intersection[ref_side%n_nodes].second;
932 s.reset(e.side_ptr(ref_side%n_nodes).release());
933 p = s->point(0) + xi_ref * (s->point(1) - s->point(0));
934 nd =
new libMesh::Node(p);
939 _elem->node_ptr((ref_side+1)%n_nodes));
940 side_p0 = side_nondim_points[ref_side%n_nodes].first;
941 side_p1 = side_nondim_points[ref_side%n_nodes].second;
951 it0 = node_phi_vals.find(s->node_ptr(0));
952 v0 = it0->second.first;
955 ref_side_node0_positive =
true;
959 it0 = node_phi_vals.find(e.node_ptr(ref_node+1));
960 v0 = it0->second.first;
963 ref_side_node0_positive =
true;
974 xi_other = side_intersection[(ref_side+2)%n_nodes].second;
975 s.reset(e.side_ptr((ref_side+2)%n_nodes).release());
976 p = s->point(0) + xi_other * (s->point(1) - s->point(0));
977 nd =
new libMesh::Node(p);
982 _elem->node_ptr((ref_side+3)%n_nodes));
983 side_p0 = side_nondim_points[(ref_side+2)%n_nodes].first;
984 side_p1 = side_nondim_points[(ref_side+2)%n_nodes].second;
988 *e_p =
const_cast<libMesh::Elem*
>(&e),
989 *e1 = libMesh::Elem::build(libMesh::QUAD4, e_p).release(),
990 *e2 = libMesh::Elem::build(libMesh::QUAD4, e_p).release();
1008 e1->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+1)%n_nodes));
1009 e1->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+2)%n_nodes));
1027 e2->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+3)%n_nodes));
1028 e2->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr(ref_side));
1033 if (ref_side_node0_positive) {
1050 xi_other = side_intersection[(ref_side+1)%n_nodes].second;
1051 s.reset(e.side_ptr((ref_side+1)%n_nodes).release());
1052 p = s->point(0) + xi_other * (s->point(1) - s->point(0));
1053 nd =
new libMesh::Node(p);
1058 _elem->node_ptr((ref_side+2)%n_nodes));
1059 side_p0 = side_nondim_points[(ref_side+1)%n_nodes].first;
1060 side_p1 = side_nondim_points[(ref_side+1)%n_nodes].second;
1066 s.reset(e.side_ptr((ref_side+2)%n_nodes).release());
1067 p = s->point(1) + xi_ref * (s->point(0) - s->point(1));
1068 nd =
new libMesh::Node(p);
1073 _elem->node_ptr((ref_side+3)%n_nodes));
1074 side_p0 = side_nondim_points[(ref_side+2)%n_nodes].first;
1075 side_p1 = side_nondim_points[(ref_side+2)%n_nodes].second;
1076 _node_local_coords[nd] = side_p1 + xi_ref * (side_p0 - side_p1);
1084 *e_p =
const_cast<libMesh::Elem*
>(&e),
1085 *e1 = libMesh::Elem::build( libMesh::TRI3, e_p).release(),
1086 *e2 = libMesh::Elem::build(libMesh::QUAD4, e_p).release(),
1087 *e3 = libMesh::Elem::build(libMesh::QUAD4, e_p).release();
1104 e1->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+1)%n_nodes));
1124 e2->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+3)%n_nodes));
1125 e2->set_node(3) =
const_cast<libMesh::Node*
>(e.node_ptr(ref_side));
1143 e3->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+2)%n_nodes));
1149 if (ref_side_node0_positive) {
1169 *e_p =
const_cast<libMesh::Elem*
>(&e),
1170 *e1 = libMesh::Elem::build(libMesh::TRI3, e_p).release(),
1171 *e2 = libMesh::Elem::build(libMesh::QUAD4, e_p).release();
1176 if (ref_side-ref_node == 1) {
1188 e1->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node)%n_nodes));
1189 e1->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+1)%n_nodes));
1207 e2->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+1)%n_nodes));
1208 e2->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+2)%n_nodes));
1209 e2->set_node(3) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node)%n_nodes));
1215 if (ref_side_node0_positive) {
1226 else if (ref_side-ref_node==2) {
1238 e1->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node)%n_nodes));
1240 e1->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+3)%n_nodes));
1256 e2->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node)%n_nodes));
1257 e2->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+1)%n_nodes));
1258 e2->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+2)%n_nodes));
1264 if (ref_side_node0_positive) {
1285 *e_p =
const_cast<libMesh::Elem*
>(&e),
1286 *e1 = libMesh::Elem::build(libMesh::TRI3, e_p).release(),
1287 *e2 = libMesh::Elem::build(libMesh::TRI3, e_p).release();
1302 e1->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node)%n_nodes));
1303 e1->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+1)%n_nodes));
1304 e1->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+2)%n_nodes));
1318 e2->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+2)%n_nodes));
1319 e2->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+3)%n_nodes));
1320 e2->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr(ref_node));
1324 if (ref_side_node0_positive) {
1341 xi_other = side_intersection[(ref_side+1)%n_nodes].second;
1342 s.reset(e.side_ptr((ref_side+1)%n_nodes).release());
1343 p = s->point(0) + xi_other * (s->point(1) - s->point(0));
1344 nd =
new libMesh::Node(p);
1349 _elem->node_ptr((ref_side+2)%n_nodes));
1350 side_p0 = side_nondim_points[(ref_side+1)%n_nodes].first;
1351 side_p1 = side_nondim_points[(ref_side+1)%n_nodes].second;
1356 *e_p =
const_cast<libMesh::Elem*
>(&e),
1357 *e1 = libMesh::Elem::build(libMesh::TRI3, e_p).release(),
1358 *e2 = libMesh::Elem::build(libMesh::TRI3, e_p).release(),
1359 *e3 = libMesh::Elem::build(libMesh::TRI3, e_p).release(),
1360 *e4 = libMesh::Elem::build(libMesh::TRI3, e_p).release();
1377 e1->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node)%n_nodes));
1378 e1->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+1)%n_nodes));
1394 e2->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node)%n_nodes));
1396 e2->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+3)%n_nodes));
1411 e3->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node)%n_nodes));
1413 e3->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+2)%n_nodes));
1428 e4->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node)%n_nodes));
1429 e4->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+2)%n_nodes));
1436 if (ref_side_node0_positive) {
1456 for (
unsigned int i=1; i<4; i++) {
1458 xi_other = side_intersection[(ref_side+i)%n_nodes].second;
1459 s.reset(e.side_ptr((ref_side+i)%n_nodes).release());
1460 p = s->point(0) + xi_other * (s->point(1) - s->point(0));
1461 nd =
new libMesh::Node(p);
1466 _elem->node_ptr((ref_side+i+1)%n_nodes));
1467 side_p0 = side_nondim_points[(ref_side+i)%n_nodes].first;
1468 side_p1 = side_nondim_points[(ref_side+i)%n_nodes].second;
1477 *e_p =
const_cast<libMesh::Elem*
>(&e),
1478 *e1 = libMesh::Elem::build( libMesh::TRI3, e_p).release(),
1479 *e2 = libMesh::Elem::build( libMesh::TRI3, e_p).release(),
1480 *e3 = libMesh::Elem::build(libMesh::QUAD4, e_p).release(),
1481 *e4 = libMesh::Elem::build(libMesh::QUAD4, e_p).release();
1499 e1->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+1)%n_nodes));
1517 e2->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+3)%n_nodes));
1534 e3->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr(ref_side));
1555 e4->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+2)%n_nodes));
1560 if (ref_side_node0_positive) {
1587 (
const libMesh::Point& p0,
1588 const libMesh::Point& p1,
1615 while (fabs(v) >
_tol &&
1619 pt = pt0 + (pt1 - pt0)*xi;
1648 const libMesh::Point&
1650 (
const libMesh::Node& n)
const {
1654 std::map<const libMesh::Node*, libMesh::Point>::const_iterator
1669 for (
unsigned int i=0; i<
_new_nodes.size(); i++)
1690 std::pair<const libMesh::Node*, const libMesh::Node*>
1697 std::map<const libMesh::Node*, std::pair<const libMesh::Node*, const libMesh::Node*>>::const_iterator
1710 libmesh_assert_equal_to(sides.size(), 0);
1712 std::map<const libMesh::Node*, std::pair<Real, bool> >::const_iterator
1716 for (
unsigned int i=0; i<
_elem->n_sides(); i++) {
1718 std::unique_ptr<const libMesh::Elem> side(
_elem->side_ptr(i).release());
1723 for (
unsigned int j=0; j<side->n_nodes(); j++) {
1727 libmesh_assert(it != end);
1730 if (!(it->second.second || it->second.first >
_tol)) {
1732 on_material =
false;
1748 libMesh::Point &pt) {
1753 std::map<const libMesh::Node*, std::pair<Real, bool> >::const_iterator
1764 for ( ; it != end; it++) {
1766 if (it->second.second) {
1768 dp = *it->first - p;
1770 if (dp.norm() < dist) {
1778 for (
unsigned int i=0; i<
_new_nodes.size(); i++) {
1782 if (std::fabs(v) <=
_tol) {
1784 dp = *_new_nodes[i] - p;
1786 if (dp.norm() < dist) {
1787 pt = *_new_nodes[i];
unsigned int edge_on_boundary() const
MAST::LevelSet2DIntersectionMode _mode
const MAST::FieldFunction< Real > * _phi
const std::vector< const libMesh::Elem * > & get_sub_elems_positive_phi() const
unsigned int get_side_on_interface(const libMesh::Elem &e) const
Real _find_intersection_on_straight_edge(const libMesh::Point &p0, const libMesh::Point &p1, const MAST::FieldFunction< Real > &phi, const Real t)
bool if_elem_has_positive_phi_region() const
const libMesh::Elem & elem() const
void get_material_sides_without_intersection(std::set< unsigned int > &sides) const
identifies the sides of the element that are completely on the material side without any intersection...
MAST::LevelSet2DIntersectionMode get_intersection_mode() const
bool _if_elem_on_negative_phi
true if element is completely on the negative side of level set with no intersection ...
virtual ~LevelSetIntersection()
Real get_node_phi_value(const libMesh::Node *n) const
std::unique_ptr< libMesh::Elem > _first_order_elem(const libMesh::Elem &e)
creates a first order element from the given high-order element.
bool if_node_is_new(const libMesh::Node &node) const
identifies if the node from the subelements is a new node or an existing node from the parent element...
bool if_elem_on_positive_phi() const
bool if_elem_on_negative_phi() const
bool if_hanging_node(const libMesh::Node *n) const
The case of two adjacent edges results in a new node on an edge that is not coincident with the level...
bool _if_elem_on_positive_phi
true if element is completely on the positive side of level set with no intersection ...
std::map< const libMesh::Elem *, int > _elem_sides_on_interface
std::map< const libMesh::Node *, std::pair< const libMesh::Node *, const libMesh::Node * > > _bounding_nodes
std::pair< const libMesh::Node *, const libMesh::Node * > get_bounding_nodes_for_node(const libMesh::Node &node) const
for new nodes required to create the subelements this method returns the nodes on an edge that bound ...
const unsigned int _max_elem_divs
void _add_node_local_coords(const libMesh::Elem &e, std::vector< std::pair< libMesh::Point, libMesh::Point > > &side_nondim_points, std::map< const libMesh::Node *, libMesh::Point > &node_coord_map)
void _find_quad4_intersections(const MAST::FieldFunction< Real > &phi, const libMesh::Elem &e, const Real t, const std::map< const libMesh::Node *, std::pair< Real, bool > > &node_phi_vals)
void init(const MAST::FieldFunction< Real > &phi, const libMesh::Elem &e, const Real t, unsigned int max_elem_id, unsigned int max_node_id)
const libMesh::Elem * _elem
std::vector< libMesh::Elem * > _new_elems
std::vector< const libMesh::Elem * > _positive_phi_elems
std::map< const libMesh::Node *, libMesh::Point > _node_local_coords
unsigned int _max_mesh_node_id
std::vector< libMesh::Node * > _new_nodes
bool if_intersection_through_elem() const
Real get_positive_phi_volume_fraction() const
bool if_interior_node(const libMesh::Node &node) const
identifies if the new node is on an edge along the level-set method in the interior of the element (a...
bool has_side_on_interface(const libMesh::Elem &e) const
void get_corner_nodes_on_negative_phi(std::set< const libMesh::Node *> &nodes) const
unsigned int node_on_boundary() const
bool if_elem_has_boundary() const
const std::vector< const libMesh::Elem * > & get_sub_elems_negative_phi() const
unsigned int _node_num_on_boundary
bool if_elem_has_negative_phi_region() const
std::vector< const libMesh::Elem * > _negative_phi_elems
const libMesh::Point & get_nondimensional_coordinate_for_node(const libMesh::Node &n) const
std::set< const libMesh::Node * > _interior_nodes
std::map< const libMesh::Node *, std::pair< Real, bool > > _node_phi_vals
unsigned int _max_mesh_elem_id
void _init_on_first_order_ref_elem(const MAST::FieldFunction< Real > &phi, const libMesh::Elem &e, const Real t)
initializes on a reference element that is a first-order counterpart of the given high-order element...
void get_nearest_intersection_point(const libMesh::Point &p, libMesh::Point &pt)
void clear()
clears the data structures
unsigned int _edge_num_on_boundary
LevelSet2DIntersectionMode
std::set< const libMesh::Node * > _hanging_node