Reference documentation for deal.II version 8.4.2
grid_reordering.cc
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 2000 - 2015 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 
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>
22 
23 #include <algorithm>
24 #include <set>
25 #include <iostream>
26 #include <fstream>
27 #include <functional>
28 
29 DEAL_II_NAMESPACE_OPEN
30 
31 
32 template<>
33 void
35  const bool)
36 {
37  // there should not be much to do
38  // in 1d...
39 }
40 
41 
42 template<>
43 void
45  std::vector<CellData<1> > &)
46 {
47  // nothing to be done in 1d
48 }
49 
50 template<>
51 void
53  const bool)
54 {
55  // there should not be much to do
56  // in 1d...
57 }
58 
59 
60 template<>
61 void
63  std::vector<CellData<1> > &)
64 {
65  // nothing to be done in 1d
66 }
67 
68 
69 template<>
70 void
72  const bool)
73 {
74  // there should not be much to do
75  // in 1d...
76 }
77 
78 
79 template<>
80 void
82  std::vector<CellData<1> > &)
83 {
84  // nothing to be done in 1d
85 }
86 
87 
88 namespace internal
89 {
90  namespace GridReordering2d
91  {
92 // -- Definition of connectivity information --
93  const int ConnectGlobals::EdgeToNode[4][2] =
94  { {0,1},{1,2},{2,3},{3,0} };
95 
96  const int ConnectGlobals::NodeToEdge[4][2] =
97  { {3,0},{0,1},{1,2},{2,3} };
98 
99  const int ConnectGlobals::DefaultOrientation[4][2] =
100  {{0,1},{1,2},{3,2},{0,3}};
101 
102 
110  struct Edge
111  {
112  Edge (const unsigned int v0,
113  const unsigned int v1)
114  :
115  v0(v0), v1(v1)
116  {}
117 
118  const unsigned int v0, v1;
119  bool operator < (const Edge &e) const
120  {
121  return ((v0 < e.v0) || ((v0 == e.v0) && (v1 < e.v1)));
122  }
123  };
124 
125 
126  bool
127  is_consistent (const std::vector<CellData<2> > &cells)
128  {
129  std::set<Edge> edges;
130 
131  std::vector<CellData<2> >::const_iterator c = cells.begin();
132  for (; c != cells.end(); ++c)
133  {
134  // construct the four edges
135  // in reverse order
136  const Edge reverse_edges[4] = { Edge (c->vertices[1],
137  c->vertices[0]),
138  Edge (c->vertices[2],
139  c->vertices[1]),
140  Edge (c->vertices[2],
141  c->vertices[3]),
142  Edge (c->vertices[3],
143  c->vertices[0])
144  };
145  // for each of them, check
146  // whether they are already
147  // in the set
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()))
152  return false;
153  // ok, not. insert them
154  // in the order in which
155  // we want them
156  // (std::set eliminates
157  // duplicated by itself)
158  for (unsigned int i = 0; i<4; ++i)
159  {
160  const Edge e(reverse_edges[i].v1, reverse_edges[i].v0);
161  edges.insert (e);
162  }
163  // then go on with next
164  // cell
165  }
166  // no conflicts found, so
167  // return true
168  return true;
169  }
170 
171 
172 
173  struct MSide::SideRectify : public std::unary_function<MSide,void>
174  {
175  void operator() (MSide &s) const
176  {
177  if (s.v0>s.v1)
178  std::swap (s.v0, s.v1);
179  }
180  };
181 
182 
183  struct MSide::SideSortLess : public std::binary_function<MSide,MSide,bool>
184  {
185  bool operator()(const MSide &s1, const MSide &s2) const
186  {
187  int s1vmin,s1vmax;
188  int s2vmin,s2vmax;
189  if (s1.v0<s1.v1)
190  {
191  s1vmin = s1.v0;
192  s1vmax = s1.v1;
193  }
194  else
195  {
196  s1vmin = s1.v1;
197  s1vmax = s1.v0;
198  }
199  if (s2.v0<s2.v1)
200  {
201  s2vmin = s2.v0;
202  s2vmax = s2.v1;
203  }
204  else
205  {
206  s2vmin = s2.v1;
207  s2vmax = s2.v0;
208  }
209 
210  if (s1vmin<s2vmin)
211  return true;
212  if (s1vmin>s2vmin)
213  return false;
214  return s1vmax<s2vmax;
215  }
216  };
217 
218 
223  MSide quadside(const CellData<2> &q, unsigned int i)
224  {
225  Assert (i<4, ExcInternalError());
226  return MSide(q.vertices[ConnectGlobals::EdgeToNode[i][0]],
227  q.vertices[ConnectGlobals::EdgeToNode[i][1]]);
228  }
229 
230 
234  struct QuadSide: public std::binary_function<CellData<2>,int,MSide>
235  {
236  MSide operator()(const CellData<2> &q, int i) const
237  {
238  return quadside(q,i);
239  }
240  };
241 
242 
243 
244  MQuad::MQuad (const unsigned int v0,
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,
252  const CellData<2> &cd)
253  :
254  original_cell_data (cd)
255  {
256  v[0] = v0;
257  v[1] = v1;
258  v[2] = v2;
259  v[3] = v3;
260  side[0] = s0;
261  side[1] = s1;
262  side[2] = s2;
263  side[3] = s3;
264  }
265 
266 
267  MSide::MSide (const unsigned int initv0,
268  const unsigned int initv1)
269  :
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),
275  Oriented(false)
276  {}
277 
278 
279 
280  bool
281  MSide::operator == (const MSide &s2) const
282  {
283  if ((v0 == s2.v0)&&(v1 == s2.v1))
284  {
285  return true;
286  }
287  if ((v0 == s2.v1)&&(v1 == s2.v0))
288  {
289  return true;
290  }
291  return false;
292  }
293 
294 
295  bool
296  MSide::operator != (const MSide &s2) const
297  {
298  return !(*this == s2);
299  }
300 
301 
302  namespace
303  {
310  MQuad build_quad_from_vertices(const CellData<2> &q,
311  const std::vector<MSide> &elist)
312  {
313  // compute the indices of the four
314  // sides that bound this quad. note
315  // that the incoming list elist is
316  // sorted with regard to the
317  // MSide::SideSortLess criterion
318  unsigned int edges[4] = { numbers::invalid_unsigned_int,
321  numbers::invalid_unsigned_int
322  };
323 
324  for (unsigned int i=0; i<4; ++i)
325  edges[i] = (Utilities::lower_bound (elist.begin(),
326  elist.end(),
327  quadside(q,i),
328  MSide::SideSortLess())
329  -
330  elist.begin());
331 
332  return MQuad(q.vertices[0],q.vertices[1], q.vertices[2], q.vertices[3],
333  edges[0], edges[1], edges[2], edges[3],
334  q);
335  }
336  }
337 
338 
339 
340  void
341  GridReordering::reorient(std::vector<CellData<2> > &quads)
342  {
343  build_graph(quads);
344  orient();
345  get_quads(quads);
346  }
347 
348 
349  void
350  GridReordering::build_graph (const std::vector<CellData<2> > &inquads)
351  {
352  //Reserve some space
353  sides.reserve(4*inquads.size());
354 
355  //Insert all the sides into the side vector
356  for (int i = 0; i<4; ++i)
357  {
358  std::transform(inquads.begin(),inquads.end(),
359  std::back_inserter(sides), std::bind2nd(QuadSide(),i));
360  }
361 
362  //Change each edge so that v0<v1
363  std::for_each(sides.begin(),sides.end(),
364  MSide::SideRectify() );
365 
366  //Sort them by Sidevertices.
367  std::sort(sides.begin(),sides.end(),
368  MSide::SideSortLess());
369 
370  //Remove duplicates
371  sides.erase(std::unique(sides.begin(),sides.end()),
372  sides.end());
373 
374  // Swap trick to shrink the
375  // side vector
376  std::vector<MSide>(sides).swap(sides);
377 
378  // Now assign the correct sides to
379  // each quads
380  mquads.reserve(inquads.size());
381  std::transform(inquads.begin(),
382  inquads.end(),
383  std::back_inserter(mquads),
384  std_cxx11::bind(build_quad_from_vertices,
385  std_cxx11::_1,
386  std_cxx11::cref(sides)) );
387 
388  // Assign the quads to their sides also.
389  int qctr = 0;
390  for (std::vector<MQuad>::iterator it = mquads.begin(); it != mquads.end(); ++it)
391  {
392  for (unsigned int i = 0; i<4; ++i)
393  {
394  MSide &ss = sides[(*it).side[i]];
395  if (ss.Q0 == numbers::invalid_unsigned_int)
396  {
397  ss.Q0 = qctr;
398  ss.lsn0 = i;
399  }
400  else if (ss.Q1 == numbers::invalid_unsigned_int)
401  {
402  ss.Q1 = qctr;
403  ss.lsn1 = i;
404  }
405  else
406  AssertThrow (false, ExcInternalError());
407  }
408  qctr++;
409  }
410  }
411 
412 
414  {
415  // do what the comment in the
416  // class declaration says
417  unsigned int qnum = 0;
418  while (get_unoriented_quad(qnum))
419  {
420  unsigned int lsn = 0;
421  while (get_unoriented_side(qnum,lsn))
422  {
423  orient_side(qnum,lsn);
424  unsigned int qqnum = qnum;
425  while (side_hop(qqnum,lsn))
426  {
427  // switch this face
428  lsn = (lsn+2)%4;
429  if (!is_oriented_side(qqnum,lsn))
430  orient_side(qqnum,lsn);
431  else
432  //We've found a
433  //cycle.. and
434  //oriented all
435  //quads in it.
436  break;
437  }
438  }
439  }
440  }
441 
442 
443  void
444  GridReordering::orient_side(const unsigned int quadnum,
445  const unsigned int localsidenum)
446  {
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]];
451 
452  //is the opposite side oriented?
453  if (op_side.Oriented)
454  {
455  //YES - Make the orientations match
456  //Is op side in default orientation?
457  if (op_side.v0 == quad.v[ConnectGlobals::DefaultOrientation[op_side_l][0]])
458  {
459  //YES
460  side.v0 = quad.v[ConnectGlobals::DefaultOrientation[localsidenum][0]];
461  side.v1 = quad.v[ConnectGlobals::DefaultOrientation[localsidenum][1]];
462  }
463  else
464  {
465  //NO, its reversed
466  side.v0 = quad.v[ConnectGlobals::DefaultOrientation[localsidenum][1]];
467  side.v1 = quad.v[ConnectGlobals::DefaultOrientation[localsidenum][0]];
468  }
469  }
470  else
471  {
472  //NO
473  //Just use the default orientation
474  side.v0 = quad.v[ConnectGlobals::DefaultOrientation[localsidenum][0]];
475  side.v1 = quad.v[ConnectGlobals::DefaultOrientation[localsidenum][1]];
476  }
477  side.Oriented = true;
478  }
479 
480 
481 
482  bool
483  GridReordering::is_fully_oriented_quad(const unsigned int quadnum) const
484  {
485  return (
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)
490  );
491  }
492 
493 
494 
495  bool
496  GridReordering::is_oriented_side(const unsigned int quadnum,
497  const unsigned int lsn) const
498  {
499  return (sides[mquads[quadnum].side[lsn]].Oriented);
500  }
501 
502 
503 
504 
505  bool
506  GridReordering::get_unoriented_quad(unsigned int &UnOrQLoc) const
507  {
508  while ( (UnOrQLoc<mquads.size()) &&
509  is_fully_oriented_quad(UnOrQLoc) )
510  UnOrQLoc++;
511  return (UnOrQLoc != mquads.size());
512  }
513 
514 
515 
516  bool
517  GridReordering::get_unoriented_side (const unsigned int quadnum,
518  unsigned int &lsn) const
519  {
520  const MQuad &mq = mquads[quadnum];
521  if (!sides[mq.side[0]].Oriented)
522  {
523  lsn = 0;
524  return true;
525  }
526  if (!sides[mq.side[1]].Oriented)
527  {
528  lsn = 1;
529  return true;
530  }
531  if (!sides[mq.side[2]].Oriented)
532  {
533  lsn = 2;
534  return true;
535  }
536  if (!sides[mq.side[3]].Oriented)
537  {
538  lsn = 3;
539  return true;
540  }
541  return false;
542  }
543 
544 
545  bool
546  GridReordering::side_hop (unsigned int &qnum, unsigned int &lsn) const
547  {
548  const MQuad &mq = mquads[qnum];
549  const MSide &s = sides[mq.side[lsn]];
550  unsigned int opquad = 0;
551  if (s.Q0 == qnum)
552  {
553  opquad = s.Q1;
554  lsn = s.lsn1;
555  }
556  else
557  {
558  opquad = s.Q0;
559  lsn = s.lsn0;
560  }
561 
562  if (opquad != numbers::invalid_unsigned_int)
563  {
564  qnum = opquad;
565  return true;
566  }
567 
568  return false;
569  }
570 
571 
572  void
573  GridReordering::get_quads (std::vector<CellData<2> > &outquads) const
574  {
575  outquads.clear();
576  outquads.reserve(mquads.size());
577  for (unsigned int qn = 0; qn<mquads.size(); ++qn)
578  {
579  // initialize CellData object with
580  // previous contents, and the
581  // overwrite all the fields that
582  // might have changed in the
583  // process of rotating things
584  CellData<2> q = mquads[qn].original_cell_data;
585 
586  // Are the sides oriented?
587  Assert (is_fully_oriented_quad(qn), ExcInternalError());
588  bool s[4]; //whether side 1 ,2, 3, 4 are in the default orientation
589  for (int sn = 0; sn<4; sn++)
590  {
591  s[sn] = is_side_default_oriented(qn,sn);
592  }
593  // Are they oriented in the "deal way"?
594  Assert (s[0] == s[2], ExcInternalError());
595  Assert (s[1] == s[3], ExcInternalError());
596  // How much we rotate them by.
597  int rotn = 2*(s[0]?1:0)+ ((s[0]^s[1])?1:0);
598 
599  for (int i = 0; i<4; ++i)
600  {
601  q.vertices[(i+rotn)%4] = mquads[qn].v[i];
602  }
603  outquads.push_back(q);
604  }
605 
606  }
607 
608  bool
610  const unsigned int lsn) const
611  {
612  return (sides[mquads[qnum].side[lsn]].v0 ==
613  mquads[qnum].v[ConnectGlobals::DefaultOrientation[lsn][0]]);
614  }
615  } // namespace GridReordering2d
616 } // namespace internal
617 
618 
619 // anonymous namespace for internal helper functions
620 namespace
621 {
631  void
632  reorder_new_to_old_style (std::vector<CellData<2> > &cells)
633  {
634  for (unsigned int cell=0; cell<cells.size(); ++cell)
635  std::swap(cells[cell].vertices[2], cells[cell].vertices[3]);
636  }
637 
638 
639  void
640  reorder_new_to_old_style (std::vector<CellData<3> > &cells)
641  {
642  unsigned int tmp[GeometryInfo<3>::vertices_per_cell];
643  for (unsigned int cell=0; cell<cells.size(); ++cell)
644  {
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)
648  cells[cell].vertices[i] = tmp[GeometryInfo<3>::ucd_to_deal[i]];
649  }
650  }
651 
652 
656  void
657  reorder_old_to_new_style (std::vector<CellData<2> > &cells)
658  {
659  // just invert the permutation:
660  reorder_new_to_old_style(cells);
661  }
662 
663 
664  void
665  reorder_old_to_new_style (std::vector<CellData<3> > &cells)
666  {
667  // undo the ordering above
668  unsigned int tmp[GeometryInfo<3>::vertices_per_cell];
669  for (unsigned int cell=0; cell<cells.size(); ++cell)
670  {
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)
674  cells[cell].vertices[GeometryInfo<3>::ucd_to_deal[i]] = tmp[i];
675  }
676  }
677 }
678 
679 
680 template<>
681 void
682 GridReordering<2>::reorder_cells (std::vector<CellData<2> > &cells,
683  const bool use_new_style_ordering)
684 {
685  // if necessary, convert to old-style format
686  if (use_new_style_ordering)
687  reorder_new_to_old_style(cells);
688 
689  // check if grids are already
690  // consistent. if so, do
691  // nothing. if not, then do the
692  // reordering
695 
696 
697  // and convert back if necessary
698  if (use_new_style_ordering)
699  reorder_old_to_new_style(cells);
700 }
701 
702 
703 template<>
704 void
705 GridReordering<2,3>::reorder_cells (std::vector<CellData<2> > &cells,
706  const bool use_new_style_ordering)
707 {
708  // if necessary, convert to old-style format
709  if (use_new_style_ordering)
710  reorder_new_to_old_style(cells);
711 
713 
714 
715  // and convert back if necessary
716  if (use_new_style_ordering)
717  reorder_old_to_new_style(cells);
718 }
719 
720 
721 
722 template<>
723 void
724 GridReordering<2>::invert_all_cells_of_negative_grid(const std::vector<Point<2> > &all_vertices,
725  std::vector<CellData<2> > &cells)
726 {
727  unsigned int vertices_lex[GeometryInfo<2>::vertices_per_cell];
728  unsigned int n_negative_cells=0;
729  for (unsigned int cell_no=0; cell_no<cells.size(); ++cell_no)
730  {
731  // GridTools::cell_measure
732  // requires the vertices to be
733  // in lexicographic ordering
734  for (unsigned int i=0; i<GeometryInfo<2>::vertices_per_cell; ++i)
735  vertices_lex[GeometryInfo<2>::ucd_to_deal[i]]=cells[cell_no].vertices[i];
736  if (GridTools::cell_measure<2>(all_vertices, vertices_lex) < 0)
737  {
738  ++n_negative_cells;
739  std::swap(cells[cell_no].vertices[1], cells[cell_no].vertices[3]);
740 
741  // check whether the
742  // resulting cell is now ok.
743  // if not, then the grid is
744  // seriously broken and
745  // should be sticked into the
746  // bin
747  for (unsigned int i=0; i<GeometryInfo<2>::vertices_per_cell; ++i)
748  vertices_lex[GeometryInfo<2>::ucd_to_deal[i]]=cells[cell_no].vertices[i];
749  AssertThrow(GridTools::cell_measure<2>(all_vertices, vertices_lex) > 0,
750  ExcInternalError());
751  }
752  }
753 
754  // We assume that all cells of a grid have
755  // either positive or negative volumes but
756  // not both mixed. Although above reordering
757  // might work also on single cells, grids
758  // with both kind of cells are very likely to
759  // be broken. Check for this here.
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 ")
770  + Utilities::to_string (cells.size())
771  + " cells in the mesh, "
772  + Utilities::to_string (n_negative_cells)
773  + " appear to have a negative volume."));
774 }
775 
776 
777 
778 template<>
779 void
781  std::vector<CellData<2> > &)
782 {
783  Assert(false, ExcNotImplemented());
784 }
785 
786 
787 
788 namespace internal
789 {
790  namespace GridReordering3d
791  {
792  DeclException1 (ExcGridOrientError,
793  char *,
794  << "Grid Orientation Error: " << arg1);
795 
796  const EdgeOrientation unoriented_edge = {'u'};
797  const EdgeOrientation forward_edge = {'f'};
798  const EdgeOrientation backward_edge = {'b'};
799 
800 
801  inline
802  bool
803  EdgeOrientation::
804  operator == (const EdgeOrientation &edge_orientation) const
805  {
806  Assert ((orientation == 'u') || (orientation == 'f') || (orientation == 'b'),
807  ExcInternalError());
808  return orientation == edge_orientation.orientation;
809  }
810 
811 
812 
813  inline
814  bool
815  EdgeOrientation::
816  operator != (const EdgeOrientation &edge_orientation) const
817  {
818  return ! (*this == edge_orientation);
819  }
820 
821 
822 
823  namespace ElementInfo
824  {
832  static const unsigned int edge_to_node[8][3] =
833  {
834  {0,4,8},
835  {0,5,9},
836  {3,5,10},
837  {3,4,11},
838  {1,7,8},
839  {1,6,9},
840  {2,6,10},
841  {2,7,11}
842  };
843 
844 
855  static const EdgeOrientation edge_to_node_orient[8][3] =
856  {
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}
865  };
866 
873  static const unsigned int nodes_on_edge[12][2] =
874  {
875  {0,1},
876  {4,5},
877  {7,6},
878  {3,2},
879  {0,3},
880  {1,2},
881  {5,6},
882  {4,7},
883  {0,4},
884  {1,5},
885  {2,6},
886  {3,7}
887  };
888  }
889 
890 
891  CheapEdge::CheapEdge (const unsigned int n0,
892  const unsigned int n1)
893  :
894  // sort the
895  // entries so
896  // that
897  // node0<node1
898  node0(std::min (n0, n1)),
899  node1(std::max (n0, n1))
900  {}
901 
902 
903 
904  bool CheapEdge::operator< (const CheapEdge &e2) const
905  {
906  if (node0 < e2.node0) return true;
907  if (node0 > e2.node0) return false;
908  if (node1 < e2.node1) return true;
909  return false;
910  }
911 
912 
913  Edge::Edge (const unsigned int n0,
914  const unsigned int n1)
915  :
916  orientation_flag (unoriented_edge),
917  group (numbers::invalid_unsigned_int)
918  {
919  nodes[0] = n0;
920  nodes[1] = n1;
921  }
922 
923 
924 
926  {
927  for (unsigned int i=0; i<GeometryInfo<3>::lines_per_cell; ++i)
928  {
930  local_orientation_flags[i] = forward_edge;
931  }
932 
933  for (unsigned int i=0; i<GeometryInfo<3>::vertices_per_cell; ++i)
935 
936  waiting_to_be_processed = false;
937  }
938 
939 
940 
941  Mesh::Mesh (const std::vector<CellData<3> > &incubes)
942  {
943  // copy the cells into our own
944  // internal data format.
945  const unsigned int numelems = incubes.size();
946  for (unsigned int i=0; i<numelems; ++i)
947  {
948  Cell the_cell;
949  std::copy (&incubes[i].vertices[0],
950  &incubes[i].vertices[GeometryInfo<3>::vertices_per_cell],
951  &the_cell.nodes[0]);
952 
953  cell_list.push_back(the_cell);
954  }
955 
956  // then build edges and
957  // connectivity
958  build_connectivity ();
959  }
960 
961 
962 
963  void
965  {
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);
969  }
970 
971 
972 
973  void
975  const unsigned int local_node_num) const
976  {
977 #ifdef DEBUG
978  // check that every edge
979  // coming into a node has the
980  // same node value
981 
982  // Get the Local Node Numbers
983  // of the incoming edges
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];
987 
988  // Global Edge Numbers
989  const unsigned int ge0 = c.edges[e0];
990  const unsigned int ge1 = c.edges[e1];
991  const unsigned int ge2 = c.edges[e2];
992 
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] ==
1000  c.local_orientation_flags[e2] ?
1001  forward_edge : backward_edge;
1002 
1003  // Make sure that edges agree
1004  // what the current node should
1005  // be.
1006  Assert ((edge_list[ge0].nodes[or0 == forward_edge ? 0 : 1] ==
1007  edge_list[ge1].nodes[or1 == forward_edge ? 0 : 1])
1008  &&
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"));
1013 #else
1014  (void)c;
1015  (void)local_node_num;
1016 #endif
1017  }
1018 
1019 
1020 
1021  // This is the guts of the matter...
1023  {
1024  const unsigned int n_cells = cell_list.size();
1025 
1026  unsigned int n_edges = 0;
1027  // Correctly build the edge
1028  // list
1029  {
1030  // edge_map stores the
1031  // edge_number associated
1032  // with a given CheapEdge
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;
1037  ++cur_cell_id)
1038  {
1039  // Get the local node
1040  // numbers on edge
1041  // edge_num
1042  const Cell &cur_cell = cell_list[cur_cell_id];
1043 
1044  for (unsigned short int edge_num = 0;
1045  edge_num<12;
1046  ++edge_num)
1047  {
1048  unsigned int gl_edge_num = 0;
1049  EdgeOrientation l_edge_orient = forward_edge;
1050 
1051  // Construct the
1052  // CheapEdge
1053  const unsigned int
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);
1057 
1058  if (edge_map.count(cur_edge) == 0)
1059  // Edge not in map
1060  {
1061  // put edge in
1062  // hash map with
1063  // ctr value;
1064  edge_map[cur_edge] = ctr;
1065  gl_edge_num = ctr;
1066 
1067  // put the edge
1068  // into the
1069  // global edge
1070  // list
1071  edge_list.push_back(Edge(node0,node1));
1072  ctr++;
1073  }
1074  else
1075  {
1076  // get edge_num
1077  // from hash_map
1078  gl_edge_num = edge_map[cur_edge];
1079  if (edge_list[gl_edge_num].nodes[0] != node0)
1080  l_edge_orient = backward_edge;
1081  }
1082  // set edge number to
1083  // edgenum
1084  cell_list[cur_cell_id].edges[edge_num] = gl_edge_num;
1085  cell_list[cur_cell_id].local_orientation_flags[edge_num]
1086  = l_edge_orient;
1087  }
1088  }
1089  n_edges = ctr;
1090  }
1091 
1092  // Count each of the edges.
1093  {
1094  std::vector<int> edge_count(n_edges,0);
1095 
1096 
1097  // Count every time an edge
1098  // occurs in a cube.
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]];
1102 
1103  // So we now know how many
1104  // cubes contain a given
1105  // edge. Just need to store
1106  // the list of cubes in the
1107  // edge
1108 
1109  // Allocate the space for the
1110  // neighbor list
1111  for (unsigned int cur_edge_id=0; cur_edge_id<n_edges; ++cur_edge_id)
1112  edge_list[cur_edge_id].neighboring_cubes
1113  .resize (edge_count[cur_edge_id]);
1114 
1115  // Store the position of the
1116  // current neighbor in the
1117  // edge's neighbor list
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)
1121  {
1122  const unsigned int
1123  gl_edge_id = cell_list[cur_cell_id].edges[edge_num];
1124  Edge &cur_edge = edge_list[gl_edge_id];
1125  cur_edge.neighboring_cubes[cur_cell_edge_list_posn[gl_edge_id]]
1126  = cur_cell_id;
1127  cur_cell_edge_list_posn[gl_edge_id]++;
1128  }
1129  }
1130  }
1131 
1132 
1133 
1134  void
1135  Mesh::export_to_deal_format (std::vector<CellData<3> > &outcubes) const
1136  {
1137  Assert (outcubes.size() == cell_list.size(),
1138  ExcInternalError());
1139 
1140  // simply overwrite the output
1141  // array with the new
1142  // information
1143  for (unsigned int i=0; i<cell_list.size(); ++i)
1144  std::copy (&cell_list[i].nodes[0],
1145  &cell_list[i].nodes[GeometryInfo<3>::vertices_per_cell],
1146  &outcubes[i].vertices[0]);
1147  }
1148 
1149 
1150 
1151  Orienter::Orienter (const std::vector<CellData<3> > &incubes)
1152  :
1153  mesh (incubes),
1154  cur_posn (0),
1155  marker_cube (0),
1156  cur_edge_group (0)
1157  {
1158  for (unsigned int i = 0; i<12; ++i)
1159  edge_orient_array[i] = false;
1160  }
1161 
1162 
1163 
1164  bool Orienter::orient_mesh (std::vector<CellData<3> > &incubes)
1165  {
1166  Orienter orienter (incubes);
1167 
1168  // First check that the mesh is
1169  // sensible
1170  orienter.mesh.sanity_check ();
1171 
1172  // Orient the mesh
1173 
1174  // if not successful, break here, else go
1175  // on
1176  if (!orienter.orient_edges ())
1177  return false;
1178 
1179  // Now we have a bunch of oriented
1180  // edges int the structure we only
1181  // have to turn the cubes so they
1182  // match the edge orientation.
1183  orienter.orient_cubes ();
1184 
1185  // Copy the elements from our
1186  // internal structure back into
1187  // their original location.
1188  orienter.mesh.export_to_deal_format (incubes);
1189  // reordering was successful
1190  return true;
1191  }
1192 
1200  {
1201  // While there are still cubes
1202  // to orient
1203  while (get_next_unoriented_cube())
1204  // And there are edges in
1205  // the cube to orient
1206  while (orient_next_unoriented_edge())
1207  {
1208  // Make all the sides
1209  // in the current set
1210  // match
1211  orient_edges_in_current_cube();
1212 
1213  // Add the adjacent
1214  // cubes to the list
1215  // for processing
1216  get_adjacent_cubes();
1217  // Start working on
1218  // this list of cubes
1219  while (get_next_active_cube())
1220  {
1221  // Make sure the
1222  // Cube doesn't
1223  // have a
1224  // contradiction
1226  return false;
1227 
1228  // If we needed to
1229  // orient any edges
1230  // in the current
1231  // cube then we may
1232  // have to process
1233  // the neighbor.
1234  if (orient_edges_in_current_cube())
1235  get_adjacent_cubes();
1236  }
1237 
1238  // start the next sheet
1239  // (equivalence class
1240  // of edges)
1241  ++cur_edge_group;
1242  }
1243  return true;
1244  }
1245 
1246 
1247 
1248  bool Orienter::get_next_unoriented_cube ()
1249  {
1250  // The last cube in the list
1251  const unsigned int n_cubes = mesh.cell_list.size();
1252  // Keep shifting along the list
1253  // until we find a cube which
1254  // is not fully oriented or the
1255  // end.
1256  while ( (marker_cube<n_cubes) &&
1258  ++marker_cube;
1260  // Return true if we now point
1261  // at a valid cube.
1262  return (cur_posn < n_cubes);
1263  }
1264 
1265 
1266 
1267  bool Orienter::is_oriented (const unsigned int cell_num) const
1268  {
1269  for (unsigned int i=0; i<12; ++i)
1270  if (mesh.edge_list[mesh.cell_list[cell_num].edges[i]].orientation_flag
1271  == unoriented_edge)
1272  return false;
1273  return true;
1274  }
1275 
1276 
1277 
1278  bool
1279  Orienter::cell_is_consistent(const unsigned int cell_num) const
1280  {
1281 
1282  const Cell &c = mesh.cell_list[cell_num];
1283 
1284  // Checks that all oriented
1285  // edges in the group are
1286  // oriented consistently.
1287  for (unsigned int group=0; group<3; ++group)
1288  {
1289  // When a nonzero
1290  // orientation is first
1291  // encountered in the group
1292  // it is stored in this
1293  EdgeOrientation value = unoriented_edge;
1294  // Loop over all parallel
1295  // edges
1296  for (unsigned int i=4*group; i<4*(group+1); ++i)
1297  {
1298  // If the edge has
1299  // orientation
1300  if ((c.local_orientation_flags[i] !=
1301  unoriented_edge)
1302  &&
1303  (mesh.edge_list[c.edges[i]].orientation_flag !=
1304  unoriented_edge))
1305  {
1306  const EdgeOrientation this_edge_direction
1307  = (c.local_orientation_flags[i]
1308  == mesh.edge_list[c.edges[i]].orientation_flag ?
1309  forward_edge : backward_edge);
1310 
1311  // If we haven't
1312  // seen an oriented
1313  // edge before,
1314  // then store its
1315  // value:
1316  if (value == unoriented_edge)
1317  value = this_edge_direction;
1318  else
1319  // If we have
1320  // seen an
1321  // oriented edge
1322  // in this group
1323  // we'd better
1324  // have the same
1325  // orientation.
1326  if (value != this_edge_direction)
1327  return false;
1328  }
1329  }
1330  }
1331  return true;
1332  }
1333 
1334 
1335 
1336  bool Orienter::orient_next_unoriented_edge ()
1337  {
1339  const Cell &c = mesh.cell_list[cur_posn];
1340  unsigned int edge = 0;
1341 
1342  // search for the unoriented
1343  // side
1344  while ((edge<12) &&
1345  (mesh.edge_list[c.edges[edge]].orientation_flag !=
1346  unoriented_edge))
1347  ++edge;
1348 
1349  // if we found none then return
1350  // false
1351  if (edge == 12)
1352  return false;
1353 
1354  // Which edge group we're in.
1355  const unsigned int edge_group = edge/4;
1356 
1357  // A sanity check that none of
1358  // the other edges in the group
1359  // have been oriented yet Each
1360  // of the edges in the group
1361  // should be un-oriented
1362  for (unsigned int j = edge_group*4; j<edge_group*4+4; ++j)
1363  Assert (mesh.edge_list[c.edges[j]].orientation_flag ==
1364  unoriented_edge,
1365  ExcGridOrientError("Tried to orient edge when other edges "
1366  "in group are already oriented!"));
1367 
1368  // Make the edge alignment
1369  // match that of the local
1370  // cube.
1371  mesh.edge_list[c.edges[edge]].orientation_flag
1372  = c.local_orientation_flags[edge];
1373  mesh.edge_list[c.edges[edge]].group = cur_edge_group;
1374 
1375  // Remember that we have oriented
1376  // this edge in the current cell.
1377  edge_orient_array[edge] = true;
1378 
1379  return true;
1380  }
1381 
1382 
1383 
1384  bool Orienter::orient_edges_in_current_cube ()
1385  {
1386  for (unsigned int edge_group=0; edge_group<3; ++edge_group)
1387  if (orient_edge_set_in_current_cube(edge_group) == true)
1388  return true;
1389 
1390  return false;
1391  }
1392 
1393 
1394 
1395  bool
1396  Orienter::orient_edge_set_in_current_cube (const unsigned int n)
1397  {
1398  const Cell &c = mesh.cell_list[cur_posn];
1399 
1400  // Check if any edge is
1401  // oriented
1402  unsigned int n_oriented = 0;
1403  EdgeOrientation glorient = unoriented_edge;
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)
1407  {
1408  if ((mesh.edge_list[c.edges[i]].orientation_flag !=
1409  unoriented_edge)
1410  &&
1411  (c.local_orientation_flags[i] !=
1412  unoriented_edge))
1413  {
1414  ++n_oriented;
1415 
1416  const EdgeOrientation orient
1417  = (mesh.edge_list[c.edges[i]].orientation_flag ==
1419  forward_edge : backward_edge);
1420 
1421  if (glorient == unoriented_edge)
1422  glorient = orient;
1423  else
1424  AssertThrow(orient == glorient,
1425  ExcGridOrientError("Attempted to Orient Misaligned cube"));
1426  }
1427  else
1428  edge_flags |= cur_flag;
1429  }
1430 
1431  // were any of the sides
1432  // oriented? were they all
1433  // already oriented?
1434  if ((glorient == unoriented_edge) || (n_oriented == 4))
1435  return false;
1436 
1437  // If so orient all edges
1438  // consistently.
1439  cur_flag = 1;
1440  for (unsigned int i=4*n; i<4*(n+1); ++i, cur_flag<<=1)
1441  if ((edge_flags & cur_flag) != 0)
1442  {
1443  mesh.edge_list[c.edges[i]].orientation_flag
1444  = (c.local_orientation_flags[i] == glorient ?
1445  forward_edge : backward_edge);
1446 
1447  mesh.edge_list[c.edges[i]].group = cur_edge_group;
1448  // Remember that we have oriented
1449  // this edge in the current cell.
1450  edge_orient_array[i] = true;
1451  }
1452 
1453  return true;
1454  }
1455 
1456 
1457 
1458  void Orienter::get_adjacent_cubes ()
1459  {
1460  const Cell &c = mesh.cell_list[cur_posn];
1461  for (unsigned int e=0; e<12; ++e)
1462  // Only need to add the adjacent
1463  // cubes for edges we recently
1464  // oriented
1465  if (edge_orient_array[e] == true)
1466  {
1467  const Edge &the_edge = mesh.edge_list[c.edges[e]];
1468  for (unsigned int local_cube_num = 0;
1469  local_cube_num < the_edge.neighboring_cubes.size();
1470  ++local_cube_num)
1471  {
1472  const unsigned int
1473  global_cell_num = the_edge.neighboring_cubes[local_cube_num];
1474  Cell &ncell = mesh.cell_list[global_cell_num];
1475 
1476  // If the cell is waiting to be
1477  // processed we dont want to add
1478  // it to the list a second time.
1479  if (!ncell.waiting_to_be_processed)
1480  {
1481  sheet_to_process.push_back(global_cell_num);
1482  ncell.waiting_to_be_processed = true;
1483  }
1484  }
1485  }
1486  // we're done with this cube so
1487  // clear its processing flags.
1488  for (unsigned int e=0; e<12; ++e)
1489  edge_orient_array[e] = false;
1490 
1491  }
1492 
1493 
1494 
1495  bool Orienter::get_next_active_cube ()
1496  {
1497  // Mark the curent Cube as
1498  // finished with.
1499  Cell &c = mesh.cell_list[cur_posn];
1500  c.waiting_to_be_processed = false;
1501  if (sheet_to_process.empty() == false)
1502  {
1503  cur_posn = sheet_to_process.back();
1504  sheet_to_process.pop_back();
1505  return true;
1506  }
1507  return false;
1508  }
1509 
1510 
1512  {
1513  // We assume that the mesh has
1514  // all edges oriented already.
1515 
1516  // This is a list of
1517  // permutations that take node
1518  // 0 to node i but only rotate
1519  // the cube. (This set is far
1520  // from unique (there are 3 for
1521  // each node - for our
1522  // algorithm it doesn't matter
1523  // which of the three we use)
1524  static const unsigned int CubePermutations[8][8] =
1525  {
1526  {0,1,2,3,4,5,6,7},
1527  {1,2,3,0,5,6,7,4},
1528  {2,3,0,1,6,7,4,5},
1529  {3,0,1,2,7,4,5,6},
1530  {4,7,6,5,0,3,2,1},
1531  {5,4,7,6,1,0,3,2},
1532  {6,5,4,7,2,1,0,3},
1533  {7,6,5,4,3,2,1,0}
1534  };
1535 
1536  // So now we need to work out
1537  // which node needs to be
1538  // mapped to the zero node.
1539  // The trick is that the node
1540  // that should be the local
1541  // zero node has three edges
1542  // coming into it.
1543  for (unsigned int i=0; i<mesh.cell_list.size(); ++i)
1544  {
1545  Cell &the_cell = mesh.cell_list[i];
1546 
1547  // This stores whether the
1548  // global oriented edge
1549  // points in the same
1550  // direction as it's local
1551  // edge on the current
1552  // cube. (for each edge on
1553  // the curent cube)
1554  EdgeOrientation local_edge_orientation[12];
1555  for (unsigned int j = 0; j<12; ++j)
1556  {
1557  // get the global edge
1558  const Edge &the_edge = mesh.edge_list[the_cell.edges[j]];
1559  // All edges should be
1560  // oriented at this
1561  // stage..
1562  Assert (the_edge.orientation_flag != unoriented_edge,
1563  ExcGridOrientError ("Unoriented edge encountered"));
1564  // calculate whether it
1565  // points the right way
1566  // or not
1567  local_edge_orientation[j] = (the_cell.local_orientation_flags[j] ==
1568  the_edge.orientation_flag ?
1569  forward_edge : backward_edge);
1570  }
1571 
1572  // Here the number of
1573  // incoming edges is
1574  // tallied for each node.
1575  unsigned int perm_num = numbers::invalid_unsigned_int;
1576  for (unsigned int node_num=0; node_num<8; ++node_num)
1577  {
1578  // The local edge
1579  // numbers coming into
1580  // the node
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];
1584 
1585  // The local
1586  // orientation of the
1587  // edge coming into the
1588  // node.
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];
1592 
1593  // Add one to the total
1594  // for each edge
1595  // pointing in
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());
1602 
1603  const unsigned int
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));
1607 
1608  if (total == 3)
1609  {
1611  ExcGridOrientError("More than one node with 3 incoming "
1612  "edges found in curent hex."));
1613  perm_num = node_num;
1614  }
1615  }
1616  // We should now have a
1617  // valid permutation number
1619  ExcGridOrientError("No node having 3 incoming edges found in curent hex."));
1620 
1621  // So use the appropriate
1622  // rotation to get the new
1623  // cube
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];
1629  }
1630  }
1631  } // namespace GridReordering3d
1632 } // namespace internal
1633 
1634 
1635 
1636 template<>
1637 void
1638 GridReordering<3>::reorder_cells (std::vector<CellData<3> > &cells,
1639  const bool use_new_style_ordering)
1640 {
1641  Assert (cells.size() != 0,
1642  ExcMessage("List of elements to orient must have at least one cell"));
1643 
1644  // if necessary, convert to old-style format
1645  if (use_new_style_ordering)
1646  reorder_new_to_old_style(cells);
1647 
1648  // create a backup to use if GridReordering
1649  // was not successful
1650  std::vector<CellData<3> > backup=cells;
1651 
1652  // This does the real work
1653  const bool success=
1655 
1656  // if reordering was not successful use
1657  // original connectivity, otherwise do
1658  // nothing (i.e. use the reordered
1659  // connectivity)
1660  if (!success)
1661  cells=backup;
1662 
1663  // and convert back if necessary
1664  if (use_new_style_ordering)
1665  reorder_old_to_new_style(cells);
1666 }
1667 
1668 
1669 
1670 template<>
1671 void
1673  const std::vector<Point<3> > &all_vertices,
1674  std::vector<CellData<3> > &cells)
1675 {
1676  unsigned int vertices_lex[GeometryInfo<3>::vertices_per_cell];
1677  unsigned int n_negative_cells=0;
1678  for (unsigned int cell_no=0; cell_no<cells.size(); ++cell_no)
1679  {
1680  // GridTools::cell_measure
1681  // requires the vertices to be
1682  // in lexicographic ordering
1683  for (unsigned int i=0; i<GeometryInfo<3>::vertices_per_cell; ++i)
1684  vertices_lex[GeometryInfo<3>::ucd_to_deal[i]]=cells[cell_no].vertices[i];
1685  if (GridTools::cell_measure<3>(all_vertices, vertices_lex) < 0)
1686  {
1687  ++n_negative_cells;
1688  // reorder vertices: swap front and back face
1689  for (unsigned int i=0; i<4; ++i)
1690  std::swap(cells[cell_no].vertices[i], cells[cell_no].vertices[i+4]);
1691 
1692  // check whether the
1693  // resulting cell is now ok.
1694  // if not, then the grid is
1695  // seriously broken and
1696  // should be sticked into the
1697  // bin
1698  for (unsigned int i=0; i<GeometryInfo<3>::vertices_per_cell; ++i)
1699  vertices_lex[GeometryInfo<3>::ucd_to_deal[i]]=cells[cell_no].vertices[i];
1700  AssertThrow(GridTools::cell_measure<3>(all_vertices, vertices_lex) > 0,
1701  ExcInternalError());
1702  }
1703  }
1704 
1705  // We assume that all cells of a
1706  // grid have either positive or
1707  // negative volumes but not both
1708  // mixed. Although above reordering
1709  // might work also on single cells,
1710  // grids with both kind of cells
1711  // are very likely to be
1712  // broken. Check for this here.
1713  AssertThrow(n_negative_cells==0 || n_negative_cells==cells.size(), ExcInternalError());
1714 }
1715 
1716 
1717 DEAL_II_NAMESPACE_CLOSE
1718 
Iterator lower_bound(Iterator first, Iterator last, const T &val)
Definition: utilities.h:604
static const unsigned int invalid_unsigned_int
Definition: types.h:164
bool operator!=(const MSide &s2) const
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)
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)
STL namespace.
#define AssertThrow(cond, exc)
Definition: exceptions.h:358
Definition: point.h:89
std::string to_string(const number value, const unsigned int digits=numbers::invalid_unsigned_int)
Definition: utilities.cc:89
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)
Definition: exceptions.h:542
static bool orient_mesh(std::vector< CellData< 3 > > &incubes)
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)
Definition: exceptions.h:294
static void invert_all_cells_of_negative_grid(const std::vector< Point< spacedim > > &all_vertices, std::vector< CellData< dim > > &original_cells)
void get_quads(std::vector< CellData< 2 > > &outquads) const
std::vector< unsigned int > neighboring_cubes
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]
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
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)
MSide quadside(const CellData< 2 > &q, unsigned int i)
bool is_consistent(const std::vector< CellData< 2 > > &cells)
bool get_unoriented_side(const unsigned int quadnum, unsigned int &sidenum) const
void reorient(std::vector< CellData< 2 > > &quads)
Edge(const unsigned int n0, const unsigned int n1)
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]
Definition: tria.h:110