34 _max_mesh_elem_id (0),
35 _max_mesh_node_id (0),
39 _if_elem_on_positive_phi (false),
40 _if_elem_on_negative_phi (false),
42 _node_num_on_boundary (0),
43 _edge_num_on_boundary (0){
153 std::vector<const libMesh::Elem*>::const_iterator
159 v0 =
_elem->volume();
161 for ( ; it != end; it++)
162 v += (*it)->volume();
173 std::map<const libMesh::Node*, std::pair<Real, bool> >::const_iterator
177 libmesh_assert(it != end);
178 return it->second.first;
202 std::vector<libMesh::Elem*>::iterator
206 for ( ; e_it != e_end; e_it++)
210 std::vector<libMesh::Node*>::iterator
214 for ( ; n_it != n_end; n_it++)
224 const libMesh::Elem& e,
226 unsigned int max_elem_id,
227 unsigned int max_node_id) {
231 libmesh_assert_equal_to(e.dim(), 2);
243 case libMesh::QUAD9: {
245 std::unique_ptr<libMesh::Elem>
259 std::unique_ptr<libMesh::Elem>
262 std::unique_ptr<libMesh::Elem>
266 case libMesh::QUAD9: {
268 first_order_elem.reset(libMesh::Elem::build(libMesh::QUAD4).release());
270 for (
unsigned int i=0; i<4; i++)
271 first_order_elem->set_node(i) =
const_cast<libMesh::Node*
>(e.node_ptr(i));
273 first_order_elem->set_id() = e.id();
282 return first_order_elem;
291 const libMesh::Elem& e,
296 libmesh_assert_equal_to(e.dim(), 2);
297 libmesh_assert(
_elem);
311 n_node_intersection = 0;
319 on_level_set =
false;
322 for (
unsigned int i=0; i<
_elem->n_nodes(); i++) {
324 const libMesh::Node& n =
_elem->node_ref(i);
326 on_level_set = fabs(val) <=
_tol;
332 if (i < e.n_nodes() && on_level_set) {
334 n_node_intersection++;
336 min_val = (min_val > val)? val : min_val;
337 max_val = (max_val < val)? val : max_val;
347 if (min_val >
_tol &&
358 else if (min_val <
_tol &&
370 else if (min_val <
_tol &&
388 val1 = std::fabs(min_val)<
_tol ? 0.: min_val,
389 val2 = std::fabs(max_val)<
_tol ? 0.: max_val;
391 sign_change = (val1*val2 < 0.);
392 if (n_node_intersection == 1 &&
402 if (min_val <=
_tol &&
408 libmesh_assert_greater(max_val,
_tol);
412 std::vector<std::pair<libMesh::Point, libMesh::Point> >
424 for (
unsigned int i=0; i<e.n_sides(); i++) {
426 std::unique_ptr<const libMesh::Elem>
427 s(e.side_ptr(i).release());
430 n_nodes_on_level_set = 0;
432 for (
unsigned int j=0; j<s->n_nodes(); j++)
435 if (n_nodes_on_level_set == s->n_nodes()) {
449 else if (min_val <
_tol)
452 std::vector<std::pair<libMesh::Point, libMesh::Point> >
476 libmesh_error_msg(
"level-set intersections for elem type not handled.");
496 for (
unsigned int i=0; i<
_new_elems.size(); i++) {
498 _new_elems[i]->subdomain_id() = e.subdomain_id();
508 const std::vector<const libMesh::Elem*>&
516 const std::vector<const libMesh::Elem*>&
534 switch (
_elem->type()) {
545 std::map<const libMesh::Node*, std::pair<Real, bool>>::const_iterator
549 for (
unsigned int i=0; i<n_corner_nodes; i++) {
551 const libMesh::Node* nd =
_elem->node_ptr(i);
555 libmesh_assert(it != end);
557 if (it->second.first < 0.)
558 nodes.insert(it->first);
568 std::map<const libMesh::Elem*, int>::const_iterator it;
573 return it->second >= 0;
582 std::map<const libMesh::Elem*, int>::const_iterator it;
586 libmesh_assert(it->second >= 0);
594 (
const libMesh::Elem& e,
595 std::vector<std::pair<libMesh::Point, libMesh::Point> >& side_nondim_points,
596 std::map<const libMesh::Node*, libMesh::Point>& node_coord_map) {
600 case libMesh::QUAD4: {
605 side_nondim_points.resize(4);
607 side_nondim_points[0] =
608 std::pair<libMesh::Point, libMesh::Point>
609 (libMesh::Point(-1, -1, 0.),
610 libMesh::Point(+1, -1, 0.));
611 side_nondim_points[1] =
612 std::pair<libMesh::Point, libMesh::Point>
613 (libMesh::Point(+1, -1, 0.),
614 libMesh::Point(+1, +1, 0.));
615 side_nondim_points[2] =
616 std::pair<libMesh::Point, libMesh::Point>
617 (libMesh::Point(+1, +1, 0.),
618 libMesh::Point(-1, +1, 0.));
619 side_nondim_points[3] =
620 std::pair<libMesh::Point, libMesh::Point>
621 (libMesh::Point(-1, +1, 0.),
622 libMesh::Point(-1, -1, 0.));
626 for (
unsigned int i=0; i<4; i++)
627 node_coord_map[e.node_ptr(i)] = side_nondim_points[i].first;
632 libmesh_assert(
false);
641 const libMesh::Elem& e,
643 const std::map<
const libMesh::Node*, std::pair<Real, bool> >&
646 libmesh_assert_equal_to(e.type(), libMesh::QUAD4);
649 std::vector<std::pair<libMesh::Point, libMesh::Point> >
656 std::vector<std::pair<bool, Real> >
657 side_intersection(n_nodes, std::pair<bool, Real>(
false, 0.));
659 node_intersection(n_nodes,
false);
661 std::map<const libMesh::Node*, std::pair<Real, bool> >::const_iterator
664 it_end = node_phi_vals.end();
671 for (
unsigned int i=0; i<n_nodes; i++) {
673 it0 = node_phi_vals.find(e.node_ptr(i));
674 libmesh_assert(it0 != it_end);
677 if (std::fabs(it0->second.first) <
_tol)
678 node_intersection[i] =
true;
682 it1 = node_phi_vals.find(e.node_ptr((i+1)%n_nodes));
683 libmesh_assert(it1 != it_end);
684 v0 = it0->second.first;
685 v1 = it1->second.first;
686 if (std::fabs(v0) >
_tol &&
687 std::fabs(v1) >
_tol &&
691 side_intersection[i] = std::pair<bool, Real>
709 std::vector<std::pair<bool, Real> >::const_iterator
710 it = side_intersection.begin(),
711 end = side_intersection.end();
713 for (; it != end; it++)
714 n_intersection += it->first;
719 std::vector<bool>::const_iterator
720 it = node_intersection.begin(),
721 end = node_intersection.end();
723 for (; it != end; it++)
724 n_intersection += *it;
746 switch (n_intersection) {
748 for (
unsigned int i=0; i<n_nodes; i++) {
750 if (side_intersection[i].first &&
751 side_intersection[(i+1)%n_nodes].first) {
757 else if (side_intersection[i].first &&
758 side_intersection[(i+2)%n_nodes].first) {
764 else if (node_intersection[i] &&
765 node_intersection[(i+2)%n_nodes]) {
771 else if (node_intersection[i] &&
772 side_intersection[(i+1)%n_nodes].first) {
778 else if (node_intersection[i] &&
779 side_intersection[(i+2)%n_nodes].first) {
792 for (
unsigned int i=0; i<n_nodes; i++) {
793 if (node_intersection[i] &&
794 side_intersection[(i+1)%n_nodes].first &&
795 side_intersection[(i+2)%n_nodes].first) {
809 if (side_intersection[0].first &&
810 side_intersection[1].first &&
811 side_intersection[2].first &&
812 side_intersection[3].first) {
831 phi(e.centroid(), t, mid_phi);
832 it0 = node_phi_vals.find(e.node_ptr(0));
833 v0 = it0->second.first;
835 if (mid_phi * v0 > 0.)
883 libmesh_assert_equal_to(
_new_nodes.size(), 0);
888 std::unique_ptr<const libMesh::Elem>
892 ref_side_node0_positive =
false;
913 xi_ref = side_intersection[ref_side%n_nodes].second;
914 s.reset(e.side_ptr(ref_side%n_nodes).release());
915 p = s->point(0) + xi_ref * (s->point(1) - s->point(0));
916 nd =
new libMesh::Node(p);
920 side_p0 = side_nondim_points[ref_side%n_nodes].first;
921 side_p1 = side_nondim_points[ref_side%n_nodes].second;
931 it0 = node_phi_vals.find(s->node_ptr(0));
932 v0 = it0->second.first;
935 ref_side_node0_positive =
true;
939 it0 = node_phi_vals.find(e.node_ptr(ref_node+1));
940 v0 = it0->second.first;
943 ref_side_node0_positive =
true;
954 xi_other = side_intersection[(ref_side+2)%n_nodes].second;
955 s.reset(e.side_ptr((ref_side+2)%n_nodes).release());
956 p = s->point(0) + xi_other * (s->point(1) - s->point(0));
957 nd =
new libMesh::Node(p);
961 side_p0 = side_nondim_points[(ref_side+2)%n_nodes].first;
962 side_p1 = side_nondim_points[(ref_side+2)%n_nodes].second;
966 *e_p =
const_cast<libMesh::Elem*
>(&e),
967 *e1 = libMesh::Elem::build(libMesh::QUAD4, e_p).release(),
968 *e2 = libMesh::Elem::build(libMesh::QUAD4, e_p).release();
986 e1->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+1)%n_nodes));
987 e1->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+2)%n_nodes));
1005 e2->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+3)%n_nodes));
1006 e2->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr(ref_side));
1011 if (ref_side_node0_positive) {
1028 xi_other = side_intersection[(ref_side+1)%n_nodes].second;
1029 s.reset(e.side_ptr((ref_side+1)%n_nodes).release());
1030 p = s->point(0) + xi_other * (s->point(1) - s->point(0));
1031 nd =
new libMesh::Node(p);
1035 side_p0 = side_nondim_points[(ref_side+1)%n_nodes].first;
1036 side_p1 = side_nondim_points[(ref_side+1)%n_nodes].second;
1042 s.reset(e.side_ptr((ref_side+2)%n_nodes).release());
1043 p = s->point(1) + xi_ref * (s->point(0) - s->point(1));
1044 nd =
new libMesh::Node(p);
1048 side_p0 = side_nondim_points[(ref_side+2)%n_nodes].first;
1049 side_p1 = side_nondim_points[(ref_side+2)%n_nodes].second;
1050 _node_local_coords[nd] = side_p1 + xi_ref * (side_p0 - side_p1);
1058 *e_p =
const_cast<libMesh::Elem*
>(&e),
1059 *e1 = libMesh::Elem::build( libMesh::TRI3, e_p).release(),
1060 *e2 = libMesh::Elem::build(libMesh::QUAD4, e_p).release(),
1061 *e3 = libMesh::Elem::build(libMesh::QUAD4, e_p).release();
1078 e1->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+1)%n_nodes));
1097 e2->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+3)%n_nodes));
1098 e2->set_node(3) =
const_cast<libMesh::Node*
>(e.node_ptr(ref_side));
1116 e3->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+2)%n_nodes));
1122 if (ref_side_node0_positive) {
1142 *e_p =
const_cast<libMesh::Elem*
>(&e),
1143 *e1 = libMesh::Elem::build(libMesh::TRI3, e_p).release(),
1144 *e2 = libMesh::Elem::build(libMesh::QUAD4, e_p).release();
1149 if (ref_side-ref_node == 1) {
1161 e1->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node)%n_nodes));
1162 e1->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+1)%n_nodes));
1180 e2->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+1)%n_nodes));
1181 e2->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+2)%n_nodes));
1182 e2->set_node(3) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node)%n_nodes));
1188 if (ref_side_node0_positive) {
1199 else if (ref_side-ref_node==2) {
1211 e1->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node)%n_nodes));
1213 e1->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+3)%n_nodes));
1229 e2->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node)%n_nodes));
1230 e2->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+1)%n_nodes));
1231 e2->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+2)%n_nodes));
1237 if (ref_side_node0_positive) {
1258 *e_p =
const_cast<libMesh::Elem*
>(&e),
1259 *e1 = libMesh::Elem::build(libMesh::TRI3, e_p).release(),
1260 *e2 = libMesh::Elem::build(libMesh::TRI3, e_p).release();
1275 e1->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node)%n_nodes));
1276 e1->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+1)%n_nodes));
1277 e1->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+2)%n_nodes));
1291 e2->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+2)%n_nodes));
1292 e2->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+3)%n_nodes));
1293 e2->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr(ref_node));
1297 if (ref_side_node0_positive) {
1314 xi_other = side_intersection[(ref_side+1)%n_nodes].second;
1315 s.reset(e.side_ptr((ref_side+1)%n_nodes).release());
1316 p = s->point(0) + xi_other * (s->point(1) - s->point(0));
1317 nd =
new libMesh::Node(p);
1321 side_p0 = side_nondim_points[(ref_side+1)%n_nodes].first;
1322 side_p1 = side_nondim_points[(ref_side+1)%n_nodes].second;
1327 *e_p =
const_cast<libMesh::Elem*
>(&e),
1328 *e1 = libMesh::Elem::build(libMesh::TRI3, e_p).release(),
1329 *e2 = libMesh::Elem::build(libMesh::TRI3, e_p).release(),
1330 *e3 = libMesh::Elem::build(libMesh::TRI3, e_p).release(),
1331 *e4 = libMesh::Elem::build(libMesh::TRI3, e_p).release();
1348 e1->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node)%n_nodes));
1349 e1->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+1)%n_nodes));
1365 e2->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node)%n_nodes));
1367 e2->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+3)%n_nodes));
1382 e3->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node)%n_nodes));
1384 e3->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+2)%n_nodes));
1399 e4->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node)%n_nodes));
1400 e4->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_node+2)%n_nodes));
1407 if (ref_side_node0_positive) {
1427 for (
unsigned int i=1; i<4; i++) {
1429 xi_other = side_intersection[(ref_side+i)%n_nodes].second;
1430 s.reset(e.side_ptr((ref_side+i)%n_nodes).release());
1431 p = s->point(0) + xi_other * (s->point(1) - s->point(0));
1432 nd =
new libMesh::Node(p);
1436 side_p0 = side_nondim_points[(ref_side+i)%n_nodes].first;
1437 side_p1 = side_nondim_points[(ref_side+i)%n_nodes].second;
1446 *e_p =
const_cast<libMesh::Elem*
>(&e),
1447 *e1 = libMesh::Elem::build( libMesh::TRI3, e_p).release(),
1448 *e2 = libMesh::Elem::build( libMesh::TRI3, e_p).release(),
1449 *e3 = libMesh::Elem::build(libMesh::QUAD4, e_p).release(),
1450 *e4 = libMesh::Elem::build(libMesh::QUAD4, e_p).release();
1468 e1->set_node(1) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+1)%n_nodes));
1486 e2->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+3)%n_nodes));
1503 e3->set_node(0) =
const_cast<libMesh::Node*
>(e.node_ptr(ref_side));
1524 e4->set_node(2) =
const_cast<libMesh::Node*
>(e.node_ptr((ref_side+2)%n_nodes));
1529 if (ref_side_node0_positive) {
1556 (
const libMesh::Point& p0,
1557 const libMesh::Point& p1,
1584 while (fabs(v) >
_tol &&
1588 pt = pt0 + (pt1 - pt0)*xi;
1617 const libMesh::Point&
1619 (
const libMesh::Node& n)
const {
1623 std::map<const libMesh::Node*, libMesh::Point>::const_iterator
MAST::LevelSet2DIntersectionMode _mode
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_on_negative_phi
true if element is completely on the negative side of level set with no intersection ...
virtual ~LevelSetIntersection()
unsigned int edge_on_boundary() const
unsigned int get_side_on_interface(const libMesh::Elem &e) 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_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
unsigned int node_on_boundary() const
const unsigned int _max_elem_divs
const libMesh::Point & get_nondimensional_coordinate_for_node(const libMesh::Node &n) const
const std::vector< const libMesh::Elem * > & get_sub_elems_negative_phi() const
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)
MAST::LevelSet2DIntersectionMode get_intersection_mode() const
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
const libMesh::Elem & elem() const
std::vector< const libMesh::Elem * > _positive_phi_elems
bool if_intersection_through_elem() const
Real get_node_phi_value(const libMesh::Node *n) const
std::map< const libMesh::Node *, libMesh::Point > _node_local_coords
unsigned int _max_mesh_node_id
std::vector< libMesh::Node * > _new_nodes
bool has_side_on_interface(const libMesh::Elem &e) const
bool if_elem_on_negative_phi() const
Real get_positive_phi_volume_fraction() const
bool if_elem_has_positive_phi_region() const
void get_corner_nodes_on_negative_phi(std::set< const libMesh::Node * > &nodes) const
unsigned int _node_num_on_boundary
bool if_elem_has_boundary() const
const std::vector< const libMesh::Elem * > & get_sub_elems_positive_phi() const
bool if_elem_on_positive_phi() const
std::vector< const libMesh::Elem * > _negative_phi_elems
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 clear()
clears the data structures
unsigned int _edge_num_on_boundary
LevelSet2DIntersectionMode