17 #include <deal.II/grid/grid_reordering.h> 18 #include <deal.II/grid/grid_reordering_internal.h> 19 #include <deal.II/grid/grid_tools.h> 20 #include <deal.II/base/utilities.h> 21 #include <deal.II/base/std_cxx11/bind.h> 29 DEAL_II_NAMESPACE_OPEN
90 namespace GridReordering2d
94 { {0,1},{1,2},{2,3},{3,0} };
97 { {3,0},{0,1},{1,2},{2,3} };
100 {{0,1},{1,2},{3,2},{0,3}};
112 Edge (
const unsigned int v0,
113 const unsigned int v1)
118 const unsigned int v0, v1;
119 bool operator < (
const Edge &e)
const 121 return ((v0 < e.v0) || ((v0 == e.v0) && (v1 < e.v1)));
129 std::set<Edge> edges;
131 std::vector<CellData<2> >::const_iterator c = cells.begin();
132 for (; c != cells.end(); ++c)
136 const Edge reverse_edges[4] = {
Edge (c->vertices[1],
138 Edge (c->vertices[2],
140 Edge (c->vertices[2],
142 Edge (c->vertices[3],
148 if ((edges.find (reverse_edges[0]) != edges.end()) ||
149 (edges.find (reverse_edges[1]) != edges.end()) ||
150 (edges.find (reverse_edges[2]) != edges.end()) ||
151 (edges.find (reverse_edges[3]) != edges.end()))
158 for (
unsigned int i = 0; i<4; ++i)
160 const Edge e(reverse_edges[i].v1, reverse_edges[i].v0);
173 struct MSide::SideRectify :
public std::unary_function<MSide,void>
175 void operator() (
MSide &s)
const 178 std::swap (s.v0, s.v1);
183 struct MSide::SideSortLess :
public std::binary_function<MSide,MSide,bool>
185 bool operator()(
const MSide &s1,
const MSide &s2)
const 214 return s1vmax<s2vmax;
225 Assert (i<4, ExcInternalError());
227 q.
vertices[ConnectGlobals::EdgeToNode[i][1]]);
234 struct QuadSide:
public std::binary_function<CellData<2>,int,MSide>
245 const unsigned int v1,
246 const unsigned int v2,
247 const unsigned int v3,
248 const unsigned int s0,
249 const unsigned int s1,
250 const unsigned int s2,
251 const unsigned int s3,
254 original_cell_data (cd)
268 const unsigned int initv1)
270 v0(initv0), v1(initv1),
271 Q0(
numbers::invalid_unsigned_int),
272 Q1(
numbers::invalid_unsigned_int),
273 lsn0(
numbers::invalid_unsigned_int),
274 lsn1(
numbers::invalid_unsigned_int),
283 if ((v0 == s2.v0)&&(v1 == s2.v1))
287 if ((v0 == s2.v1)&&(v1 == s2.v0))
298 return !(*
this == s2);
311 const std::vector<MSide> &elist)
321 numbers::invalid_unsigned_int
324 for (
unsigned int i=0; i<4; ++i)
328 MSide::SideSortLess())
333 edges[0], edges[1], edges[2], edges[3],
353 sides.reserve(4*inquads.size());
356 for (
int i = 0; i<4; ++i)
358 std::transform(inquads.begin(),inquads.end(),
359 std::back_inserter(sides), std::bind2nd(
QuadSide(),i));
363 std::for_each(sides.begin(),sides.end(),
364 MSide::SideRectify() );
367 std::sort(sides.begin(),sides.end(),
368 MSide::SideSortLess());
371 sides.erase(std::unique(sides.begin(),sides.end()),
376 std::vector<MSide>(sides).swap(sides);
380 mquads.reserve(inquads.size());
381 std::transform(inquads.begin(),
383 std::back_inserter(mquads),
384 std_cxx11::bind(build_quad_from_vertices,
386 std_cxx11::cref(sides)) );
390 for (std::vector<MQuad>::iterator it = mquads.begin(); it != mquads.end(); ++it)
392 for (
unsigned int i = 0; i<4; ++i)
394 MSide &ss = sides[(*it).side[i]];
417 unsigned int qnum = 0;
418 while (get_unoriented_quad(qnum))
420 unsigned int lsn = 0;
421 while (get_unoriented_side(qnum,lsn))
423 orient_side(qnum,lsn);
424 unsigned int qqnum = qnum;
425 while (side_hop(qqnum,lsn))
429 if (!is_oriented_side(qqnum,lsn))
430 orient_side(qqnum,lsn);
445 const unsigned int localsidenum)
447 MQuad &quad = mquads[quadnum];
448 int op_side_l = (localsidenum+2)%4;
449 MSide &side = sides[mquads[quadnum].side[localsidenum]];
450 const MSide &op_side = sides[mquads[quadnum].side[op_side_l]];
453 if (op_side.Oriented)
457 if (op_side.v0 == quad.
v[ConnectGlobals::DefaultOrientation[op_side_l][0]])
460 side.v0 = quad.
v[ConnectGlobals::DefaultOrientation[localsidenum][0]];
461 side.v1 = quad.
v[ConnectGlobals::DefaultOrientation[localsidenum][1]];
466 side.v0 = quad.
v[ConnectGlobals::DefaultOrientation[localsidenum][1]];
467 side.v1 = quad.
v[ConnectGlobals::DefaultOrientation[localsidenum][0]];
474 side.v0 = quad.
v[ConnectGlobals::DefaultOrientation[localsidenum][0]];
475 side.v1 = quad.
v[ConnectGlobals::DefaultOrientation[localsidenum][1]];
477 side.Oriented =
true;
486 (sides[mquads[quadnum].side[0]].Oriented)&&
487 (sides[mquads[quadnum].side[1]].Oriented)&&
488 (sides[mquads[quadnum].side[2]].Oriented)&&
489 (sides[mquads[quadnum].side[3]].Oriented)
497 const unsigned int lsn)
const 499 return (sides[mquads[quadnum].side[lsn]].Oriented);
508 while ( (UnOrQLoc<mquads.size()) &&
509 is_fully_oriented_quad(UnOrQLoc) )
511 return (UnOrQLoc != mquads.size());
518 unsigned int &lsn)
const 520 const MQuad &mq = mquads[quadnum];
521 if (!sides[mq.
side[0]].Oriented)
526 if (!sides[mq.
side[1]].Oriented)
531 if (!sides[mq.
side[2]].Oriented)
536 if (!sides[mq.
side[3]].Oriented)
548 const MQuad &mq = mquads[qnum];
550 unsigned int opquad = 0;
576 outquads.reserve(mquads.size());
577 for (
unsigned int qn = 0; qn<mquads.size(); ++qn)
587 Assert (is_fully_oriented_quad(qn), ExcInternalError());
589 for (
int sn = 0; sn<4; sn++)
591 s[sn] = is_side_default_oriented(qn,sn);
594 Assert (s[0] == s[2], ExcInternalError());
595 Assert (s[1] == s[3], ExcInternalError());
597 int rotn = 2*(s[0]?1:0)+ ((s[0]^s[1])?1:0);
599 for (
int i = 0; i<4; ++i)
601 q.
vertices[(i+rotn)%4] = mquads[qn].v[i];
603 outquads.push_back(q);
610 const unsigned int lsn)
const 612 return (sides[mquads[qnum].side[lsn]].v0 ==
613 mquads[qnum].v[ConnectGlobals::DefaultOrientation[lsn][0]]);
632 reorder_new_to_old_style (std::vector<
CellData<2> > &cells)
634 for (
unsigned int cell=0; cell<cells.size(); ++cell)
635 std::swap(cells[cell].vertices[2], cells[cell].vertices[3]);
640 reorder_new_to_old_style (std::vector<
CellData<3> > &cells)
643 for (
unsigned int cell=0; cell<cells.size(); ++cell)
645 for (
unsigned int i=0; i<GeometryInfo<3>::vertices_per_cell; ++i)
646 tmp[i] = cells[cell].vertices[i];
647 for (
unsigned int i=0; i<GeometryInfo<3>::vertices_per_cell; ++i)
657 reorder_old_to_new_style (std::vector<
CellData<2> > &cells)
660 reorder_new_to_old_style(cells);
665 reorder_old_to_new_style (std::vector<
CellData<3> > &cells)
669 for (
unsigned int cell=0; cell<cells.size(); ++cell)
671 for (
unsigned int i=0; i<GeometryInfo<3>::vertices_per_cell; ++i)
672 tmp[i] = cells[cell].vertices[i];
673 for (
unsigned int i=0; i<GeometryInfo<3>::vertices_per_cell; ++i)
683 const bool use_new_style_ordering)
686 if (use_new_style_ordering)
687 reorder_new_to_old_style(cells);
698 if (use_new_style_ordering)
699 reorder_old_to_new_style(cells);
706 const bool use_new_style_ordering)
709 if (use_new_style_ordering)
710 reorder_new_to_old_style(cells);
716 if (use_new_style_ordering)
717 reorder_old_to_new_style(cells);
728 unsigned int n_negative_cells=0;
729 for (
unsigned int cell_no=0; cell_no<cells.size(); ++cell_no)
734 for (
unsigned int i=0; i<GeometryInfo<2>::vertices_per_cell; ++i)
736 if (GridTools::cell_measure<2>(all_vertices, vertices_lex) < 0)
739 std::swap(cells[cell_no].vertices[1], cells[cell_no].vertices[3]);
747 for (
unsigned int i=0; i<GeometryInfo<2>::vertices_per_cell; ++i)
749 AssertThrow(GridTools::cell_measure<2>(all_vertices, vertices_lex) > 0,
760 AssertThrow(n_negative_cells==0 || n_negative_cells==cells.size(),
761 ExcMessage(std::string(
"This class assumes that either all cells have positive " 762 "volume, or that all cells have been specified in an " 763 "inverted vertex order so that their volume is negative. " 764 "(In the latter case, this class automatically inverts " 765 "every cell.) However, the mesh you have specified " 766 "appears to have both cells with positive and cells with " 767 "negative volume. You need to check your mesh which " 768 "cells these are and how they got there.\n" 769 "As a hint, of the total ")
771 +
" cells in the mesh, " 773 +
" appear to have a negative volume."));
783 Assert(
false, ExcNotImplemented());
790 namespace GridReordering3d
794 <<
"Grid Orientation Error: " << arg1);
796 const EdgeOrientation unoriented_edge = {
'u'};
797 const EdgeOrientation forward_edge = {
'f'};
798 const EdgeOrientation backward_edge = {
'b'};
806 Assert ((orientation ==
'u') || (orientation ==
'f') || (orientation ==
'b'),
808 return orientation == edge_orientation.
orientation;
818 return ! (*
this == edge_orientation);
823 namespace ElementInfo
832 static const unsigned int edge_to_node[8][3] =
857 {forward_edge, forward_edge, forward_edge},
858 {backward_edge, forward_edge, forward_edge},
859 {backward_edge, backward_edge, forward_edge},
860 {forward_edge, backward_edge, forward_edge},
861 {forward_edge, forward_edge, backward_edge},
862 {backward_edge, forward_edge, backward_edge},
863 {backward_edge, backward_edge, backward_edge},
864 {forward_edge, backward_edge, backward_edge}
873 static const unsigned int nodes_on_edge[12][2] =
891 CheapEdge::CheapEdge (
const unsigned int n0,
892 const unsigned int n1)
898 node0(
std::min (n0, n1)),
899 node1(
std::max (n0, n1))
914 const unsigned int n1)
916 orientation_flag (unoriented_edge),
917 group (
numbers::invalid_unsigned_int)
927 for (
unsigned int i=0; i<GeometryInfo<3>::lines_per_cell; ++i)
930 local_orientation_flags[i] = forward_edge;
933 for (
unsigned int i=0; i<GeometryInfo<3>::vertices_per_cell; ++i)
936 waiting_to_be_processed =
false;
945 const unsigned int numelems = incubes.size();
946 for (
unsigned int i=0; i<numelems; ++i)
949 std::copy (&incubes[i].vertices[0],
953 cell_list.push_back(the_cell);
958 build_connectivity ();
966 for (
unsigned int i=0; i<cell_list.size(); ++i)
967 for (
unsigned int j=0; j<8; ++j)
968 sanity_check_node (cell_list[i], j);
975 const unsigned int local_node_num)
const 984 const unsigned int e0 = ElementInfo::edge_to_node[local_node_num][0];
985 const unsigned int e1 = ElementInfo::edge_to_node[local_node_num][1];
986 const unsigned int e2 = ElementInfo::edge_to_node[local_node_num][2];
989 const unsigned int ge0 = c.
edges[e0];
990 const unsigned int ge1 = c.
edges[e1];
991 const unsigned int ge2 = c.
edges[e2];
993 const EdgeOrientation or0 = ElementInfo::edge_to_node_orient[local_node_num][0] ==
995 forward_edge : backward_edge;
996 const EdgeOrientation or1 = ElementInfo::edge_to_node_orient[local_node_num][1] ==
998 forward_edge : backward_edge;
999 const EdgeOrientation or2 = ElementInfo::edge_to_node_orient[local_node_num][2] ==
1001 forward_edge : backward_edge;
1006 Assert ((edge_list[ge0].
nodes[or0 == forward_edge ? 0 : 1] ==
1007 edge_list[ge1].
nodes[or1 == forward_edge ? 0 : 1])
1009 (edge_list[ge1].
nodes[or1 == forward_edge ? 0 : 1] ==
1010 edge_list[ge2].
nodes[or2 == forward_edge ? 0 : 1]),
1011 ExcMessage (
"This message does not satisfy the internal " 1012 "consistency check"));
1015 (void)local_node_num;
1024 const unsigned int n_cells = cell_list.size();
1026 unsigned int n_edges = 0;
1033 std::map<CheapEdge,unsigned int> edge_map;
1034 unsigned int ctr = 0;
1035 for (
unsigned int cur_cell_id = 0;
1036 cur_cell_id<n_cells;
1042 const Cell &cur_cell = cell_list[cur_cell_id];
1044 for (
unsigned short int edge_num = 0;
1048 unsigned int gl_edge_num = 0;
1054 node0 = cur_cell.
nodes[ElementInfo::nodes_on_edge[edge_num][0]],
1055 node1 = cur_cell.
nodes[ElementInfo::nodes_on_edge[edge_num][1]];
1056 const CheapEdge cur_edge (node0, node1);
1058 if (edge_map.count(cur_edge) == 0)
1064 edge_map[cur_edge] = ctr;
1071 edge_list.push_back(
Edge(node0,node1));
1078 gl_edge_num = edge_map[cur_edge];
1079 if (edge_list[gl_edge_num].
nodes[0] != node0)
1080 l_edge_orient = backward_edge;
1084 cell_list[cur_cell_id].edges[edge_num] = gl_edge_num;
1085 cell_list[cur_cell_id].local_orientation_flags[edge_num]
1094 std::vector<int> edge_count(n_edges,0);
1099 for (
unsigned int cur_cell_id=0; cur_cell_id<n_cells; ++cur_cell_id)
1100 for (
unsigned short int edge_num = 0; edge_num<12; ++edge_num)
1101 ++edge_count[cell_list[cur_cell_id].edges[edge_num]];
1111 for (
unsigned int cur_edge_id=0; cur_edge_id<n_edges; ++cur_edge_id)
1113 .resize (edge_count[cur_edge_id]);
1118 std::vector<int> cur_cell_edge_list_posn(n_edges,0);
1119 for (
unsigned int cur_cell_id=0; cur_cell_id<n_cells; ++cur_cell_id)
1120 for (
unsigned short int edge_num=0; edge_num<12; ++edge_num)
1123 gl_edge_id = cell_list[cur_cell_id].edges[edge_num];
1124 Edge &cur_edge = edge_list[gl_edge_id];
1127 cur_cell_edge_list_posn[gl_edge_id]++;
1137 Assert (outcubes.size() == cell_list.size(),
1138 ExcInternalError());
1143 for (
unsigned int i=0; i<cell_list.size(); ++i)
1144 std::copy (&cell_list[i].
nodes[0],
1146 &outcubes[i].vertices[0]);
1158 for (
unsigned int i = 0; i<12; ++i)
1203 while (get_next_unoriented_cube())
1206 while (orient_next_unoriented_edge())
1211 orient_edges_in_current_cube();
1216 get_adjacent_cubes();
1219 while (get_next_active_cube())
1234 if (orient_edges_in_current_cube())
1235 get_adjacent_cubes();
1248 bool Orienter::get_next_unoriented_cube ()
1269 for (
unsigned int i=0; i<12; ++i)
1287 for (
unsigned int group=0; group<3; ++group)
1296 for (
unsigned int i=4*group; i<4*(group+1); ++i)
1309 forward_edge : backward_edge);
1316 if (value == unoriented_edge)
1317 value = this_edge_direction;
1326 if (value != this_edge_direction)
1336 bool Orienter::orient_next_unoriented_edge ()
1340 unsigned int edge = 0;
1355 const unsigned int edge_group = edge/4;
1362 for (
unsigned int j = edge_group*4; j<edge_group*4+4; ++j)
1365 ExcGridOrientError(
"Tried to orient edge when other edges " 1366 "in group are already oriented!"));
1384 bool Orienter::orient_edges_in_current_cube ()
1386 for (
unsigned int edge_group=0; edge_group<3; ++edge_group)
1387 if (orient_edge_set_in_current_cube(edge_group) ==
true)
1396 Orienter::orient_edge_set_in_current_cube (
const unsigned int n)
1402 unsigned int n_oriented = 0;
1404 unsigned int edge_flags = 0;
1405 unsigned int cur_flag = 1;
1406 for (
unsigned int i = 4*n; i<4*(n+1); ++i, cur_flag<<=1)
1419 forward_edge : backward_edge);
1421 if (glorient == unoriented_edge)
1425 ExcGridOrientError(
"Attempted to Orient Misaligned cube"));
1428 edge_flags |= cur_flag;
1434 if ((glorient == unoriented_edge) || (n_oriented == 4))
1440 for (
unsigned int i=4*n; i<4*(n+1); ++i, cur_flag<<=1)
1441 if ((edge_flags & cur_flag) != 0)
1445 forward_edge : backward_edge);
1458 void Orienter::get_adjacent_cubes ()
1461 for (
unsigned int e=0; e<12; ++e)
1468 for (
unsigned int local_cube_num = 0;
1488 for (
unsigned int e=0; e<12; ++e)
1495 bool Orienter::get_next_active_cube ()
1524 static const unsigned int CubePermutations[8][8] =
1555 for (
unsigned int j = 0; j<12; ++j)
1563 ExcGridOrientError (
"Unoriented edge encountered"));
1569 forward_edge : backward_edge);
1576 for (
unsigned int node_num=0; node_num<8; ++node_num)
1581 const unsigned int e0 = ElementInfo::edge_to_node[node_num][0];
1582 const unsigned int e1 = ElementInfo::edge_to_node[node_num][1];
1583 const unsigned int e2 = ElementInfo::edge_to_node[node_num][2];
1589 const EdgeOrientation sign0 = ElementInfo::edge_to_node_orient[node_num][0];
1590 const EdgeOrientation sign1 = ElementInfo::edge_to_node_orient[node_num][1];
1591 const EdgeOrientation sign2 = ElementInfo::edge_to_node_orient[node_num][2];
1596 Assert (local_edge_orientation[e0] != unoriented_edge,
1597 ExcInternalError());
1598 Assert (local_edge_orientation[e1] != unoriented_edge,
1599 ExcInternalError());
1600 Assert (local_edge_orientation[e2] != unoriented_edge,
1601 ExcInternalError());
1604 total = (((local_edge_orientation[e0] == sign0) ? 1 : 0)
1605 +((local_edge_orientation[e1] == sign1) ? 1 : 0)
1606 +((local_edge_orientation[e2] == sign2) ? 1 : 0));
1611 ExcGridOrientError(
"More than one node with 3 incoming " 1612 "edges found in curent hex."));
1613 perm_num = node_num;
1619 ExcGridOrientError(
"No node having 3 incoming edges found in curent hex."));
1624 unsigned int temp[8];
1625 for (
unsigned int v=0; v<8; ++v)
1626 temp[v] = the_cell.
nodes[CubePermutations[perm_num][v]];
1627 for (
unsigned int v=0; v<8; ++v)
1628 the_cell.
nodes[v] = temp[v];
1639 const bool use_new_style_ordering)
1641 Assert (cells.size() != 0,
1642 ExcMessage(
"List of elements to orient must have at least one cell"));
1645 if (use_new_style_ordering)
1646 reorder_new_to_old_style(cells);
1650 std::vector<CellData<3> > backup=cells;
1664 if (use_new_style_ordering)
1665 reorder_old_to_new_style(cells);
1673 const std::vector<
Point<3> > &all_vertices,
1677 unsigned int n_negative_cells=0;
1678 for (
unsigned int cell_no=0; cell_no<cells.size(); ++cell_no)
1683 for (
unsigned int i=0; i<GeometryInfo<3>::vertices_per_cell; ++i)
1685 if (GridTools::cell_measure<3>(all_vertices, vertices_lex) < 0)
1689 for (
unsigned int i=0; i<4; ++i)
1690 std::swap(cells[cell_no].vertices[i], cells[cell_no].vertices[i+4]);
1698 for (
unsigned int i=0; i<GeometryInfo<3>::vertices_per_cell; ++i)
1700 AssertThrow(GridTools::cell_measure<3>(all_vertices, vertices_lex) > 0,
1701 ExcInternalError());
1713 AssertThrow(n_negative_cells==0 || n_negative_cells==cells.size(), ExcInternalError());
1717 DEAL_II_NAMESPACE_CLOSE
Iterator lower_bound(Iterator first, Iterator last, const T &val)
static const unsigned int invalid_unsigned_int
bool operator!=(const MSide &s2) const
EdgeOrientation orientation_flag
bool operator<(const CheapEdge &e2) const
void sanity_check_node(const Cell &cell, const unsigned int local_node_num) const
::ExceptionBase & ExcMessage(std::string arg1)
bool edge_orient_array[12]
MQuad(const unsigned int v0, const unsigned int v1, const unsigned int v2, const unsigned int v3, const unsigned int s0, const unsigned int s1, const unsigned int s2, const unsigned int s3, const CellData< 2 > &cd)
#define AssertThrow(cond, exc)
std::string to_string(const number value, const unsigned int digits=numbers::invalid_unsigned_int)
unsigned int nodes[GeometryInfo< 3 >::vertices_per_cell]
bool is_oriented_side(const unsigned int quadnum, const unsigned int lsn) const
#define DeclException1(Exception1, type1, outsequence)
static bool orient_mesh(std::vector< CellData< 3 > > &incubes)
static const int EdgeToNode[4][2]
static void reorder_cells(std::vector< CellData< dim > > &original_cells, const bool use_new_style_ordering=false)
Orienter(const std::vector< CellData< 3 > > &incubes)
#define Assert(cond, exc)
static void invert_all_cells_of_negative_grid(const std::vector< Point< spacedim > > &all_vertices, std::vector< CellData< dim > > &original_cells)
std::vector< Edge > edge_list
void get_quads(std::vector< CellData< 2 > > &outquads) const
std::vector< unsigned int > neighboring_cubes
static const int NodeToEdge[4][2]
MSide(const unsigned int initv0, const unsigned int initv1)
void build_graph(const std::vector< CellData< 2 > > &inquads)
EdgeOrientation local_orientation_flags[GeometryInfo< 3 >::lines_per_cell]
static const int DefaultOrientation[4][2]
bool get_unoriented_quad(unsigned int &UnOrQLoc) const
bool operator==(const MSide &s2) const
void export_to_deal_format(std::vector< CellData< 3 > > &outcubes) const
std::vector< Cell > cell_list
unsigned int edges[GeometryInfo< 3 >::lines_per_cell]
bool side_hop(unsigned int &qnum, unsigned int &lsn) const
bool is_side_default_oriented(const unsigned int qnum, const unsigned int lsn) const
bool cell_is_consistent(const unsigned int cell_num) const
bool is_fully_oriented_quad(const unsigned int quadnum) const
Mesh(const std::vector< CellData< 3 > > &incubes)
void build_connectivity()
MSide quadside(const CellData< 2 > &q, unsigned int i)
std::vector< int > sheet_to_process
bool is_consistent(const std::vector< CellData< 2 > > &cells)
bool get_unoriented_side(const unsigned int quadnum, unsigned int &sidenum) const
void sanity_check() const
void reorient(std::vector< CellData< 2 > > &quads)
unsigned int cur_edge_group
Edge(const unsigned int n0, const unsigned int n1)
bool waiting_to_be_processed
bool is_oriented(const unsigned int cell_num) const
void orient_side(const unsigned int quadnum, const unsigned int localsidenum)
unsigned int vertices[GeometryInfo< structdim >::vertices_per_cell]