moab
moab::SimplexTemplateRefiner Class Reference

#include <SimplexTemplateRefiner.hpp>

Inheritance diagram for moab::SimplexTemplateRefiner:
moab::EntityRefiner

List of all members.

Public Member Functions

 SimplexTemplateRefiner ()
 Construct a template refiner.
virtual ~SimplexTemplateRefiner ()
 Empty destructor for good form.
virtual bool refine_entity (EntityType etyp, EntityHandle entity)
 Stream a single mesh entity through the refiner.
virtual unsigned long get_heap_size_bound (int max_recursions) const
 Bound on the number of new vertices used to allocate the heap.
virtual bool set_tag_assigner (SimplexTemplateTagAssigner *ta)
 Set the function object used to decide which tag values an edge or face midpoint is assigned.
SimplexTemplateTagAssignerget_tag_assigner () const
virtual bool prepare (RefinerTagManager *tmgr, EntityRefinerOutputFunctor *ofunc)
 Set the function object used to decide whether an edge is subdivided or not.

Protected Member Functions

void refine_0_simplex (const double *v0, const void *t0, EntityHandle h0)
 "Refine" a vertex by passing it through to the output.
bool refine_1_simplex (int max_depth, const double *v0, const void *t0, EntityHandle h0, const double *v1, const void *t1, EntityHandle h1)
 Refine an edge.
bool refine_2_simplex (int max_depth, int move, const double *v0, const void *t0, EntityHandle h0, const double *v1, const void *t1, EntityHandle h1, const double *v2, const void *t2, EntityHandle h2)
 Refine a triangle.
bool refine_3_simplex (int max_depth, double *v0, void *t0, EntityHandle h0, double *v1, void *t1, EntityHandle h1, double *v2, void *t2, EntityHandle h2, double *v3, void *t3, EntityHandle h3)
 Refine a tetrahedron.
int best_tets (int *alternates, double *[14], int, int)
void assign_parametric_coordinates (int num_nodes, const double *src, double *tgt)
 This is used by refine_entity to assign parametric coordinates to corners of each element.

Static Protected Member Functions

static bool compare_Hopf_cross_string_dist (const double *v00, const double *v01, const double *v10, const double *v11)
 Returns true if || a0a1 || < || b0b1 ||.

Protected Attributes

SimplexTemplateTagAssignertag_assigner
RefinerTagManagertag_manager
std::vector< double > corner_coords
std::vector< void * > corner_tags
std::vector< EntityHandlecorner_handles
bool input_is_output

Static Protected Attributes

static int template_index [64][2]
static int permutations_from_index [24][14]
static int templates []

Detailed Description

This is a concrete subclass of EntityRefiner that implements refinement using templates applied to simplices. Entities that are not simplices are divided into tetrahedra, triangles, or lines before being processed. Points are passed through unchanged.

Author:
David Thompson
Philippe Pebay
Date:
24 December 2007

Definition at line 41 of file SimplexTemplateRefiner.hpp.


Constructor & Destructor Documentation

Construct a template refiner.

Definition at line 28 of file SimplexTemplateRefiner.cpp.

{
  this->tag_manager = 0;
  this->tag_assigner = new SimplexTemplateTagAssigner( this );
  this->corner_coords.resize( 6 * 8 ); // Hex has 8 verts w/ 6 coordinates each
  this->corner_tags.resize( 8 ); // Hex has 8 verts (this is a pointer, not the actual tag data)
  this->corner_handles.resize( 8 ); // Hex has 8 verts (this is a pointer, not actual hash data)
  this->input_is_output = false; // Until we know better
}

Empty destructor for good form.

Definition at line 39 of file SimplexTemplateRefiner.cpp.

{
  delete this->tag_assigner;
}

Member Function Documentation

void moab::SimplexTemplateRefiner::assign_parametric_coordinates ( int  num_nodes,
const double *  src,
double *  tgt 
) [protected]

This is used by refine_entity to assign parametric coordinates to corners of each element.

Definition at line 1611 of file SimplexTemplateRefiner.cpp.

{
  for ( int i = 0; i < num_nodes; ++i, src +=3, tgt += 6 )
    for ( int j = 0; j < 3; ++j )
      tgt[j] = src[j];
}
int moab::SimplexTemplateRefiner::best_tets ( int *  alternates,
double *  [14],
int  ,
int   
) [inline, protected]

Definition at line 81 of file SimplexTemplateRefiner.hpp.

{ return alternates[0]; }
bool moab::SimplexTemplateRefiner::compare_Hopf_cross_string_dist ( const double *  a0,
const double *  a1,
const double *  b0,
const double *  b1 
) [static, protected]

Returns true if || a0a1 || < || b0b1 ||.

We use this to test which triangulation has the best aspect ratio when there are 2 to choose from.

Definition at line 1623 of file SimplexTemplateRefiner.cpp.

{   
  double sq_mag_a = 0.;
  double sq_mag_b = 0.;
  for ( int i = 0; i < 3; ++ i )
    {
    double tmp;
    tmp = a0[i] - a1[i];
    sq_mag_a += tmp*tmp;
    tmp = b0[i] - b1[i];
    sq_mag_b += tmp*tmp;
    } 
  return sq_mag_a < sq_mag_b;
}
unsigned long moab::SimplexTemplateRefiner::get_heap_size_bound ( int  max_recursions) const [inline, virtual]

Bound on the number of new vertices used to allocate the heap.

This bound is based on a hexahedron that is divided into 48 tetrahedra (a point is added to the center of each face so that compatible boundaries are guaranteed on neighboring hexahedra), each of which has 4 edges.

Implements moab::EntityRefiner.

Definition at line 48 of file SimplexTemplateRefiner.hpp.

{ return 48 * 4 * ( 1 << max_recursions ) + 8; }

Set the function object used to decide whether an edge is subdivided or not.

Reimplemented from moab::EntityRefiner.

Definition at line 185 of file SimplexTemplateRefiner.cpp.

{ 
  this->tag_manager = tmgr;
  this->tag_assigner->set_tag_manager( tmgr );
  this->input_is_output = ( this->tag_manager->get_input_mesh() == this->tag_manager->get_output_mesh() );
  //this->tag_assigner->set_edge_size_evaluator( this->edge_size_evaluator );
  return this->EntityRefiner::prepare( tmgr, ofunc );
}
void moab::SimplexTemplateRefiner::refine_0_simplex ( const double *  v0,
const void *  t0,
EntityHandle  h0 
) [protected]

"Refine" a vertex by passing it through to the output.

FIXME: There is some question as to whether this should pass vertices through since there does not appear to be a distinction between vertices as points in space and vertices as degrees-of-freedom in a mesh (i.e. a vertex that is treated as a lumped-parameter model).

Definition at line 209 of file SimplexTemplateRefiner.cpp.

{
  // Ignore these arguments... the caller is responsible for calling the output functor to ensure the
  // vertex exists on the output.
  (void) v0;
  (void) t0;

  (*this->output_functor)( h0 );
  (*this->output_functor)( MBVERTEX );
}
bool moab::SimplexTemplateRefiner::refine_1_simplex ( int  max_depth,
const double *  v0,
const void *  t0,
EntityHandle  h0,
const double *  v1,
const void *  t1,
EntityHandle  h1 
) [protected]

Refine an edge.

Definition at line 222 of file SimplexTemplateRefiner.cpp.

{
  bool edge_code = false;

  double* midptc;
  void* midptt;
  // NB: If support for multiple recursive subdivisions (without a merge in between) is required,
  //     this will have to change as it assumes that h0 and h1 have only a single entry.
  EntityHandle midpth = 0;

  if ( max_depth-- > 0 )
    {
    midptc = this->heap_coord_storage();
    midptt = this->heap_tag_storage();
    int i;
    // make valgrind happy
    //vtkstd::fill( midpt0, midpt0 + 6, 0. );
    for ( i = 0; i < 6; i++ )
      midptc[i] = ( v0[i] + v1[i] ) / 2.;

    (*this->tag_assigner)( v0, t0, h0, midptc, midptt, v1, t1, h1 );
    edge_code = this->edge_size_evaluator->evaluate_edge( v0, t0, midptc, midptt, v1, t1 );
    if ( edge_code )
      {
      midpth = (*this->output_functor)( h0, h1, midptc, midptt );
      }
    }

  switch ( edge_code )
    {
    // No edges to subdivide
  case 0:
    (*this->output_functor)( h0 );
    (*this->output_functor)( h1 );
    (*this->output_functor)( MBEDGE );
    break ;

    // One edge to subdivide
  case 1:
    this->refine_1_simplex( max_depth, v0, t0, h0, midptc, midptt, midpth );
    this->refine_1_simplex( max_depth, midptc, midptt, midpth, v1, t1, h1 );
    break;
    }

  return edge_code;
}
bool moab::SimplexTemplateRefiner::refine_2_simplex ( int  max_depth,
int  move,
const double *  v0,
const void *  t0,
EntityHandle  h0,
const double *  v1,
const void *  t1,
EntityHandle  h1,
const double *  v2,
const void *  t2,
EntityHandle  h2 
) [protected]

Refine a triangle.

Definition at line 274 of file SimplexTemplateRefiner.cpp.

{
  int edge_code = 0;

  double* midpt0c;
  double* midpt1c;
  double* midpt2c;
  void* midpt0t;
  void* midpt1t;
  void* midpt2t;
  EntityHandle midpt0h;
  EntityHandle midpt1h;
  EntityHandle midpt2h;

  if ( max_depth-- > 0 )
    {
    int i;
    midpt0c = this->heap_coord_storage();
    midpt1c = this->heap_coord_storage();
    midpt2c = this->heap_coord_storage();
    midpt0t = this->heap_tag_storage();
    midpt1t = this->heap_tag_storage();
    midpt2t = this->heap_tag_storage();
    midpt0h = 0;
    midpt1h = 0;
    midpt2h = 0;
    for ( i = 0; i < 6; ++i )
      {
      midpt0c[i] = ( v0[i] + v1[i] ) / 2.;
      midpt1c[i] = ( v1[i] + v2[i] ) / 2.;
      midpt2c[i] = ( v2[i] + v0[i] ) / 2.;
      }
    (*this->tag_assigner)( v0, t0, h0, midpt0c, midpt0t, v1, t1, h1 );
    (*this->tag_assigner)( v1, t1, h1, midpt1c, midpt1t, v2, t2, h2 );
    (*this->tag_assigner)( v2, t2, h2, midpt2c, midpt2t, v0, t0, h0 );
    if ( ( move & 1 ) && this->edge_size_evaluator->evaluate_edge( v0, t0, midpt0c, midpt0t, v1, t1 ) )
      {
      edge_code += 1;
      midpt0h = (*this->output_functor)( h0, h1, midpt0c, midpt0t );
      }
    if ( ( move & 2 ) && this->edge_size_evaluator->evaluate_edge( v1, t1, midpt1c, midpt1t, v2, t2 ) )
      {
      edge_code += 2;
      midpt1h = (*this->output_functor)( h1, h2, midpt1c, midpt1t );
      }
    if ( ( move & 4 ) && this->edge_size_evaluator->evaluate_edge( v2, t2, midpt2c, midpt2t, v0, t0 ) )
      {
      edge_code += 4;
      midpt2h = (*this->output_functor)( h2, h0, midpt2c, midpt2t );
      }
    }

  switch ( edge_code )
    {
    // No edges to subdivide
  case 0:
    (*this->output_functor)( h0 );
    (*this->output_functor)( h1 );
    (*this->output_functor)( h2 );
    (*this->output_functor)( MBTRI );
    break ;

    // One edge to subdivide
  case 1:
    this->refine_2_simplex( max_depth, move | 2, v0, t0, h0,  midpt0c, midpt0t, midpt0h, v2, t2, h2 );
    this->refine_2_simplex( max_depth, move | 4, midpt0c, midpt0t, midpt0h, v1, t1, h1,  v2, t2, h2 );
    break;
  case 2:
    this->refine_2_simplex( max_depth, move | 4, v0, t0, h0, v1, t1, h1, midpt1c, midpt1t, midpt1h );
    this->refine_2_simplex( max_depth, move | 1, v0, t0, h0, midpt1c, midpt1t, midpt1h, v2, t2, h2 );
    break;
  case 4:
    this->refine_2_simplex( max_depth, move | 2, v0, t0, h0, v1, t1, h1, midpt2c, midpt2t, midpt2h );
    this->refine_2_simplex( max_depth, move | 1, midpt2c, midpt2t, midpt2h, v1, t1, h1, v2, t2, h2 );
    break;

    // Two edges to subdivide
  case 3:
    this->refine_2_simplex( max_depth, move | 4, midpt0c, midpt0t, midpt0h, v1, t1, h1, midpt1c, midpt1t, midpt1h );
    if ( this->compare_Hopf_cross_string_dist( v2, midpt0c, v0, midpt1c ) )
      {
      this->refine_2_simplex( max_depth, move | 5, midpt0c, midpt0t, midpt0h, midpt1c, midpt1t, midpt1h,   v2,      t2,      h2   );
      this->refine_2_simplex( max_depth, move | 2,   v0,      t0,      h0,    midpt0c, midpt0t, midpt0h,   v2,      t2,      h2   );
      }
    else                                         
      {
      this->refine_2_simplex( max_depth, move | 6,   v0,      t0,      h0,   midpt0c, midpt0t, midpt0h, midpt1c, midpt1t, midpt1h );
      this->refine_2_simplex( max_depth, move | 1,   v0,      t0,      h0,   midpt1c, midpt1t, midpt1h,   v2,      t2,      h2    );
      }
    break;
  case 5:
    this->refine_2_simplex( max_depth, move | 2, v0, t0, h0, midpt0c, midpt0t, midpt0h, midpt2c, midpt2t, midpt2h );
    if ( this->compare_Hopf_cross_string_dist( v2, midpt0c, v1, midpt2c ) )
      {
      this->refine_2_simplex( max_depth, move | 4, midpt0c, midpt0t, midpt0h,   v1,      t1,      h1,       v2,      t2,    h2   );
      this->refine_2_simplex( max_depth, move | 3, midpt2c, midpt2t, midpt2h, midpt0c, midpt0t, midpt0h,    v2,      t2,    h2   );
      }
    else
      {
      this->refine_2_simplex( max_depth, move | 6, midpt0c, midpt0t, midpt0h,   v1,      t1,      h1,   midpt2c, midpt2t, midpt2h );
      this->refine_2_simplex( max_depth, move | 1, midpt2c, midpt2t, midpt2h,   v1,      t1,      h1,      v2,      t2,     h2   );
      }
    break;
  case 6:
    this->refine_2_simplex( max_depth, move | 1, midpt2c, midpt2t, midpt2h, midpt1c, midpt1t, midpt1h, v2, t2, h2 );
    if ( this->compare_Hopf_cross_string_dist( v0, midpt1c, v1, midpt2c ) )
      {
      this->refine_2_simplex( max_depth, move | 3,   v0,      t0,     h0,    midpt1c, midpt1t, midpt1h, midpt2c, midpt2t, midpt2h );
      this->refine_2_simplex( max_depth, move | 4,   v0,      t0,     h0,      v1,      t1,      h1,    midpt1c, midpt1t, midpt1h );
      }
    else
      {
      this->refine_2_simplex( max_depth, move | 2,   v0,      t0,      h0,      v1,      t1,     h1,    midpt2c, midpt2t, midpt2h );
      this->refine_2_simplex( max_depth, move | 5, midpt2c, midpt2t, midpt2h,   v1,      t1,     h1,    midpt1c, midpt1t, midpt1h );
      }
    break;

    // Three edges to subdivide
  case 7:
    this->refine_2_simplex( max_depth,        7, midpt0c, midpt0t, midpt0h, midpt1c, midpt1t, midpt1h, midpt2c, midpt2t, midpt2h );
    this->refine_2_simplex( max_depth, move | 2,   v0   ,   t0   ,   h0   , midpt0c, midpt0t, midpt0h, midpt2c, midpt2t, midpt2h );
    this->refine_2_simplex( max_depth, move | 4, midpt0c, midpt0t, midpt0h,   v1   ,   t1   ,   h1   , midpt1c, midpt1t, midpt1h );
    this->refine_2_simplex( max_depth, move | 1, midpt2c, midpt2t, midpt2h, midpt1c, midpt1t, midpt1h,   v2   ,   t2   ,   h2    );
    break;
    }

  return true;
}
bool moab::SimplexTemplateRefiner::refine_3_simplex ( int  max_depth,
double *  v0,
void *  t0,
EntityHandle  h0,
double *  v1,
void *  t1,
EntityHandle  h1,
double *  v2,
void *  t2,
EntityHandle  h2,
double *  v3,
void *  t3,
EntityHandle  h3 
) [protected]

Refine a tetrahedron.

Definition at line 409 of file SimplexTemplateRefiner.cpp.

{
  int edge_code = 0;

  double* midpt0c;
  double* midpt1c;
  double* midpt2c;
  double* midpt3c;
  double* midpt4c;
  double* midpt5c;

  void* midpt0t;
  void* midpt1t;
  void* midpt2t;
  void* midpt3t;
  void* midpt4t;
  void* midpt5t;

  EntityHandle midpt0h;
  EntityHandle midpt1h;
  EntityHandle midpt2h;
  EntityHandle midpt3h;
  EntityHandle midpt4h;
  EntityHandle midpt5h;

  if ( max_depth-- > 0 )
    {
    midpt0c = this->heap_coord_storage();
    midpt1c = this->heap_coord_storage();
    midpt2c = this->heap_coord_storage();
    midpt3c = this->heap_coord_storage();
    midpt4c = this->heap_coord_storage();
    midpt5c = this->heap_coord_storage();

    midpt0t = this->heap_tag_storage();
    midpt1t = this->heap_tag_storage();
    midpt2t = this->heap_tag_storage();
    midpt3t = this->heap_tag_storage();
    midpt4t = this->heap_tag_storage();
    midpt5t = this->heap_tag_storage();

    for ( int i = 0; i < 6; ++ i )
      {
      midpt0c[i] = ( v0[i] + v1[i] ) * .5;
      midpt1c[i] = ( v1[i] + v2[i] ) * .5;
      midpt2c[i] = ( v2[i] + v0[i] ) * .5;
      midpt3c[i] = ( v0[i] + v3[i] ) * .5;
      midpt4c[i] = ( v1[i] + v3[i] ) * .5;
      midpt5c[i] = ( v2[i] + v3[i] ) * .5;
      }

    (*this->tag_assigner)( v0, t0, h0, midpt0c, midpt0t, v1, t1, h1 );
    (*this->tag_assigner)( v1, t1, h1, midpt1c, midpt1t, v2, t2, h2 );
    (*this->tag_assigner)( v2, t2, h2, midpt2c, midpt2t, v0, t0, h0 );
    (*this->tag_assigner)( v0, t0, h0, midpt3c, midpt3t, v3, t3, h3 );
    (*this->tag_assigner)( v1, t1, h1, midpt4c, midpt4t, v3, t3, h3 );
    (*this->tag_assigner)( v2, t2, h2, midpt5c, midpt5t, v3, t3, h3 );

    if ( this->edge_size_evaluator->evaluate_edge( v0, t0, midpt0c, midpt0t, v1, t1 ) )
      {
      edge_code |=  1;
      midpt0h = (*this->output_functor)( h0, h1, midpt0c, midpt0t );
      }
    if ( this->edge_size_evaluator->evaluate_edge( v1, t1, midpt1c, midpt1t, v2, t2 ) )
      {
      edge_code |=  2;
      midpt1h = (*this->output_functor)( h1, h2, midpt1c, midpt1t );
      }
    if ( this->edge_size_evaluator->evaluate_edge( v2, t2, midpt2c, midpt2t, v0, t0 ) )
      {
      edge_code |=  4;
      midpt2h = (*this->output_functor)( h2, h0, midpt2c, midpt2t );
      }
    if ( this->edge_size_evaluator->evaluate_edge( v0, t0, midpt3c, midpt3t, v3, t3 ) )
      {
      edge_code |=  8;
      midpt3h = (*this->output_functor)( h0, h3, midpt3c, midpt3t );
      }
    if ( this->edge_size_evaluator->evaluate_edge( v1, t1, midpt4c, midpt4t, v3, t3 ) )
      {
      edge_code |= 16;
      midpt4h = (*this->output_functor)( h1, h3, midpt4c, midpt4t );
      }
    if ( this->edge_size_evaluator->evaluate_edge( v2, t2, midpt5c, midpt5t, v3, t3 ) )
      {
      edge_code |= 32;
      midpt5h = (*this->output_functor)( h2, h3, midpt5c, midpt5t );
      }
    }

  double edge_length2[6];
  for ( int ei = 0; ei < 6; ++ ei )
    edge_length2[ei] = 0.;

  for ( int c = 0; c < 3; ++ c )
    {
    double tmp;
    tmp = v1[c] - v0[c];
    edge_length2[0] += tmp * tmp;
    tmp = v2[c] - v1[c];
    edge_length2[1] += tmp * tmp;
    tmp = v2[c] - v0[c];
    edge_length2[2] += tmp * tmp;
    tmp = v3[c] - v0[c];
    edge_length2[3] += tmp * tmp;
    tmp = v3[c] - v1[c];
    edge_length2[4] += tmp * tmp;
    tmp = v3[c] - v2[c];
    edge_length2[5] += tmp * tmp;
    }

  if ( ! edge_code )
    {
    // No edges to subdivide
    (*this->output_functor)( h0 );
    (*this->output_functor)( h1 );
    (*this->output_functor)( h2 );
    (*this->output_functor)( h3 );
    (*this->output_functor)( MBTET );

    return false;
    }

  double* facept0c;
  double* facept1c;
  double* facept2c;
  double* facept3c;
  facept0c = this->heap_coord_storage();
  facept1c = this->heap_coord_storage();
  facept2c = this->heap_coord_storage();
  facept3c = this->heap_coord_storage();
  double* vertex_coords[14] = {
    v0, v1, v2, v3, 
    midpt0c, midpt1c, midpt2c, 
    midpt3c, midpt4c, midpt5c,
    facept0c, facept1c, facept2c, facept3c
  };

  void* facept0t = this->heap_tag_storage();
  void* facept1t = this->heap_tag_storage();
  void* facept2t = this->heap_tag_storage();
  void* facept3t = this->heap_tag_storage();
  void* vertex_tags[14] = {
    t0, t1, t2, t3, 
    midpt0t, midpt1t, midpt2t, 
    midpt3t, midpt4t, midpt5t,
    facept0t, facept1t, facept2t, facept3t
  };

  EntityHandle vertex_hash[14] = {
    h0, h1, h2, h3,
    midpt0h, midpt1h, midpt2h,
    midpt3h, midpt4h, midpt5h,
    0, 0, 0, 0
  };

  // Generate tetrahedra that are compatible except when edge
  // lengths are equal on indeterminately subdivided faces.
  double* permuted_coords[14];
  void* permuted_tags[14];
  EntityHandle permuted_hash[14];
  double permlen[6]; // permuted edge lengths
  int C = SimplexTemplateRefiner::template_index[edge_code][0];
  int P = SimplexTemplateRefiner::template_index[edge_code][1];
  
  // 1. Permute the tetrahedron into our canonical configuration
  for ( int i = 0; i < 14; ++ i )
    {
    permuted_coords[i] = vertex_coords[SimplexTemplateRefiner::permutations_from_index[P][i]];
    permuted_tags[i] = vertex_tags[SimplexTemplateRefiner::permutations_from_index[P][i]];
    permuted_hash[i] = vertex_hash[SimplexTemplateRefiner::permutations_from_index[P][i]];
    }

  for ( int i = 4 ; i < 10; ++ i )
    {
    // permute edge lengths too
    permlen[i-4]  = edge_length2[SimplexTemplateRefiner::permutations_from_index[P][i] - 4];
    }

  int comparison_bits;
  std::stack<int*> output_tets;
  std::stack<int*> output_perm;
  std::stack<int>  output_sign;

  // cout << "Case " << C << "  Permutation " << P << endl;
  // 2. Generate tetrahedra based on the configuration.
  //    Note that case 0 is handled above (edgeCode == 0).
  
  switch ( C )
    {
    case 1: // Ruprecht-Müller Case 1
      MB_TESSELLATOR_INCR_CASE_COUNT(0);
      output_tets.push( SimplexTemplateRefiner::templates + 0 );
      output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
      output_sign.push( 1 );
      MB_TESSELLATOR_INCR_SUBCASE_COUNT(0,0);
      break;
    case 2: // Ruprecht-Müller Case 2a
      comparison_bits = 
        ( permlen[0] <= permlen[1] ? 1 : 0 ) | ( permlen[0] >= permlen[1] ? 2 : 0 ) |
        0;
      if ( ( comparison_bits & 3 ) == 3 )
        {
        // Compute face point and tag
        for ( int i = 0; i < 6; ++ i )
          {
          permuted_coords[10][i] = ( permuted_coords[0][i] + permuted_coords[2][i] ) * .375 + permuted_coords[1][i] * .25;
          }
        (*this->tag_assigner)( permuted_tags[0], permuted_tags[2], permuted_tags[1], permuted_tags[10] );
        permuted_hash[10] = (*this->output_functor)(
          permuted_hash[0], permuted_hash[2], permuted_hash[1], permuted_coords[10], permuted_tags[10] );
        }
      MB_TESSELLATOR_INCR_CASE_COUNT(1);
      output_tets.push( SimplexTemplateRefiner::templates + 9 );
      output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
      output_sign.push( 1 );
      MB_TESSELLATOR_INCR_SUBCASE_COUNT(1,0);
      switch ( comparison_bits )
        {
        case 2: // 0>1
          output_tets.push( SimplexTemplateRefiner::templates + 14 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(1,1);
          break;
        case 1: // 1>0
          output_tets.push( SimplexTemplateRefiner::templates + 14 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[13] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(1,2);
          break;
        case 3: // 0=1
          output_tets.push( SimplexTemplateRefiner::templates + 23 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(1,3);
          break;
        }
      break;
    case 3: // Ruprecht-Müller Case 2b
      MB_TESSELLATOR_INCR_CASE_COUNT(2);
      output_tets.push( SimplexTemplateRefiner::templates + 40 );
      output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
      output_sign.push( 1 );
      MB_TESSELLATOR_INCR_SUBCASE_COUNT(2,0);
      break;
    case 4: // Ruprecht-Müller Case 3a
      comparison_bits = 
        ( permlen[0] <= permlen[3] ? 1 : 0 ) | ( permlen[0] >= permlen[3] ? 2 : 0 ) |
        ( permlen[2] <= permlen[3] ? 4 : 0 ) | ( permlen[2] >= permlen[3] ? 8 : 0 ) |
        ( permlen[0] <= permlen[2] ? 16 : 0 ) | ( permlen[0] >= permlen[2] ? 32 : 0 ) |
        0;
      if ( ( comparison_bits & 3 ) == 3 )
        {
        // Compute face point and tag
        for ( int i = 0; i < 6; ++ i )
          {
          permuted_coords[11][i] = ( permuted_coords[1][i] + permuted_coords[3][i] ) * .375 + permuted_coords[0][i] * .25;
          }
        (*this->tag_assigner)( permuted_tags[1], permuted_tags[3], permuted_tags[0], permuted_tags[11] );
        permuted_hash[11] = (*this->output_functor)(
          permuted_hash[1], permuted_hash[3], permuted_hash[0], permuted_coords[11], permuted_tags[11] );
        }
      if ( ( comparison_bits & 12 ) == 12 )
        {
        // Compute face point and tag
        for ( int i = 0; i < 6; ++ i )
          {
          permuted_coords[13][i] = ( permuted_coords[2][i] + permuted_coords[3][i] ) * .375 + permuted_coords[0][i] * .25;
          }
        (*this->tag_assigner)( permuted_tags[2], permuted_tags[3], permuted_tags[0], permuted_tags[13] );
        permuted_hash[13] = (*this->output_functor)(
          permuted_hash[2], permuted_hash[3], permuted_hash[0], permuted_coords[13], permuted_tags[13] );
        }
      if ( ( comparison_bits & 48 ) == 48 )
        {
        // Compute face point and tag
        for ( int i = 0; i < 6; ++ i )
          {
          permuted_coords[10][i] = ( permuted_coords[1][i] + permuted_coords[2][i] ) * .375 + permuted_coords[0][i] * .25;
          }
        (*this->tag_assigner)( permuted_tags[1], permuted_tags[2], permuted_tags[0], permuted_tags[10] );
        permuted_hash[10] = (*this->output_functor)(
          permuted_hash[1], permuted_hash[2], permuted_hash[0], permuted_coords[10] , permuted_tags[10] );
        }
      MB_TESSELLATOR_INCR_CASE_COUNT(3);
      output_tets.push( SimplexTemplateRefiner::templates + 57 );
      output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
      output_sign.push( 1 );
      MB_TESSELLATOR_INCR_SUBCASE_COUNT(3,0);
      switch ( comparison_bits )
        {
        case 42: // 0>2>3<0
          output_tets.push( SimplexTemplateRefiner::templates + 62 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(3,1);
          break;
        case 25: // 2>3>0<2
          output_tets.push( SimplexTemplateRefiner::templates + 62 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[11] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(3,2);
          break;
        case 37: // 3>0>2<3
          output_tets.push( SimplexTemplateRefiner::templates + 62 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[3] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(3,3);
          break;
        case 21: // 3>2>0<3
          output_tets.push( SimplexTemplateRefiner::templates + 62 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[22] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(3,4);
          break;
        case 26: // 2>0>3<2
          output_tets.push( SimplexTemplateRefiner::templates + 62 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[12] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(3,5);
          break;
        case 38: // 0>3>2<0
          output_tets.push( SimplexTemplateRefiner::templates + 62 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(3,6);
          break;
        case 58: // 0=2>3<0
          output_tets.push( SimplexTemplateRefiner::templates + 75 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(3,7);
          break;
        case 29: // 2=3>0<2
          output_tets.push( SimplexTemplateRefiner::templates + 75 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[11] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(3,8);
          break;
        case 39: // 0=3>2<0
          output_tets.push( SimplexTemplateRefiner::templates + 75 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[3] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(3,9);
          break;
        case 53: // 3>0=2<3
          output_tets.push( SimplexTemplateRefiner::templates + 96 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(3,10);
          break;
        case 46: // 0>2=3<0
          output_tets.push( SimplexTemplateRefiner::templates + 96 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[11] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(3,11);
          break;
        case 27: // 2>0=3<2
          output_tets.push( SimplexTemplateRefiner::templates + 96 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[3] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(3,12);
          break;
        case 63: // 0=2=3=0
          output_tets.push( SimplexTemplateRefiner::templates + 117 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(3,13);
          break;
        }
      break;
    case 5: // Ruprecht-Müller Case 3b
      MB_TESSELLATOR_INCR_CASE_COUNT(4);
      output_tets.push( SimplexTemplateRefiner::templates + 162 );
      output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
      output_sign.push( 1 );
      MB_TESSELLATOR_INCR_SUBCASE_COUNT(4,0);
      break;
    case 6: // Ruprecht-Müller Case 3c
      comparison_bits = 
        ( permlen[0] <= permlen[1] ? 1 : 0 ) | ( permlen[0] >= permlen[1] ? 2 : 0 ) |
        ( permlen[0] <= permlen[3] ? 4 : 0 ) | ( permlen[0] >= permlen[3] ? 8 : 0 ) |
        0;
      if ( ( comparison_bits & 3 ) == 3 )
        {
        // Compute face point and tag
        for ( int i = 0; i < 6; ++ i )
          {
          permuted_coords[10][i] = ( permuted_coords[0][i] + permuted_coords[2][i] ) * .375 + permuted_coords[1][i] * .25;
          }
        (*this->tag_assigner)( permuted_tags[0], permuted_tags[2], permuted_tags[1], permuted_tags[10] );
        permuted_hash[10] = (*this->output_functor)(
          permuted_hash[0], permuted_hash[2], permuted_hash[1], permuted_coords[10], permuted_tags[10] );
        }
      if ( ( comparison_bits & 12 ) == 12 )
        {
        // Compute face point and tag
        for ( int i = 0; i < 6; ++ i )
          {
          permuted_coords[11][i] = ( permuted_coords[1][i] + permuted_coords[3][i] ) * .375 + permuted_coords[0][i] * .25;
          }
        (*this->tag_assigner)( permuted_tags[1], permuted_tags[3], permuted_tags[0], permuted_tags[11] );
        permuted_hash[11] = (*this->output_functor)(
          permuted_hash[1], permuted_hash[3], permuted_hash[0], permuted_coords[11], permuted_tags[11] );
        }
      MB_TESSELLATOR_INCR_CASE_COUNT(5);
      switch ( comparison_bits )
        {
        case 10: // 0>1,0>3
          output_tets.push( SimplexTemplateRefiner::templates + 179 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(5,0);
          break;
        case 5: // 1>0,3>0
          output_tets.push( SimplexTemplateRefiner::templates + 200 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(5,1);
          break;
        case 6: // 0>1,3>0
          output_tets.push( SimplexTemplateRefiner::templates + 221 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(5,2);
          break;
        case 9: // 1>0,0>3
          output_tets.push( SimplexTemplateRefiner::templates + 242 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(5,3);
          break;
        case 11: // 0=1,0>3
          output_tets.push( SimplexTemplateRefiner::templates + 263 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(5,4);
          break;
        case 14: // 0=3,0>1
          output_tets.push( SimplexTemplateRefiner::templates + 263 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(5,5);
          break;
        case 7: // 3>0,0=1
          output_tets.push( SimplexTemplateRefiner::templates + 292 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(5,6);
          break;
        case 13: // 1>0,0=3
          output_tets.push( SimplexTemplateRefiner::templates + 292 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(5,7);
          break;
        case 15: // 0=1,0=3
          output_tets.push( SimplexTemplateRefiner::templates + 321 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(5,8);
          break;
        }
      break;
    case 7: // Ruprecht-Müller Case 3d
      comparison_bits = 
        ( permlen[0] <= permlen[2] ? 1 : 0 ) | ( permlen[0] >= permlen[2] ? 2 : 0 ) |
        ( permlen[0] <= permlen[4] ? 4 : 0 ) | ( permlen[0] >= permlen[4] ? 8 : 0 ) |
        0;
      if ( ( comparison_bits & 3 ) == 3 )
        {
        // Compute face point and tag
        for ( int i = 0; i < 6; ++ i )
          {
          permuted_coords[10][i] = ( permuted_coords[1][i] + permuted_coords[2][i] ) * .375 + permuted_coords[0][i] * .25;
          }
        (*this->tag_assigner)( permuted_tags[1], permuted_tags[2], permuted_tags[0], permuted_tags[10] );
        permuted_hash[10] = (*this->output_functor)(
          permuted_hash[1], permuted_hash[2], permuted_hash[0], permuted_coords[10], permuted_tags[10] );
        }
      if ( ( comparison_bits & 12 ) == 12 )
        {
        // Compute face point and tag
        for ( int i = 0; i < 6; ++ i )
          {
          permuted_coords[11][i] = ( permuted_coords[0][i] + permuted_coords[3][i] ) * .375 + permuted_coords[1][i] * .25;
          }
        (*this->tag_assigner)( permuted_tags[0], permuted_tags[3], permuted_tags[1], permuted_tags[11] );
        permuted_hash[11] = (*this->output_functor)(
          permuted_hash[0], permuted_hash[3], permuted_hash[1], permuted_coords[11], permuted_tags[11] );
        }
      MB_TESSELLATOR_INCR_CASE_COUNT(6);
      switch ( comparison_bits )
        {
        case 10: // 0>4,0>2
          output_tets.push( SimplexTemplateRefiner::templates + 362 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(6,0);
          break;
        case 5: // 4>0,2>0
          output_tets.push( SimplexTemplateRefiner::templates + 383 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(6,1);
          break;
        case 9: // 0>4,2>0
          output_tets.push( SimplexTemplateRefiner::templates + 404 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(6,2);
          break;
        case 6: // 4>0,0>2
          output_tets.push( SimplexTemplateRefiner::templates + 425 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(6,3);
          break;
        case 14: // 0=4,0>2
          output_tets.push( SimplexTemplateRefiner::templates + 446 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(6,4);
          break;
        case 11: // 0=2,0>4
          output_tets.push( SimplexTemplateRefiner::templates + 446 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(6,5);
          break;
        case 13: // 2>0,0=4
          output_tets.push( SimplexTemplateRefiner::templates + 475 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(6,6);
          break;
        case 7: // 4>0,0=2
          output_tets.push( SimplexTemplateRefiner::templates + 475 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(6,7);
          break;
        case 15: // 0=4,0=2
          output_tets.push( SimplexTemplateRefiner::templates + 504 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(6,8);
          break;
        }
      break;
    case 8: // Ruprecht-Müller Case 4a
      comparison_bits = 
        ( permlen[4] <= permlen[5] ? 1 : 0 ) | ( permlen[4] >= permlen[5] ? 2 : 0 ) |
        ( permlen[3] <= permlen[4] ? 4 : 0 ) | ( permlen[3] >= permlen[4] ? 8 : 0 ) |
        0;
      if ( ( comparison_bits & 3 ) == 3 )
        {
        // Compute face point and tag
        for ( int i = 0; i < 6; ++ i )
          {
          permuted_coords[12][i] = ( permuted_coords[1][i] + permuted_coords[2][i] ) * .375 + permuted_coords[3][i] * .25;
          }
        (*this->tag_assigner)( permuted_tags[1], permuted_tags[2], permuted_tags[3], permuted_tags[12] );
        permuted_hash[12] = (*this->output_functor)(
          permuted_hash[1], permuted_hash[2], permuted_hash[3], permuted_coords[12], permuted_tags[12] );
        }
      if ( ( comparison_bits & 12 ) == 12 )
        {
        // Compute face point and tag
        for ( int i = 0; i < 6; ++ i )
          {
          permuted_coords[11][i] = ( permuted_coords[0][i] + permuted_coords[1][i] ) * .375 + permuted_coords[3][i] * .25;
          }
        (*this->tag_assigner)( permuted_tags[0], permuted_tags[1], permuted_tags[3], permuted_tags[11] );
        permuted_hash[11] = (*this->output_functor)(
          permuted_hash[0], permuted_hash[1], permuted_hash[3], permuted_coords[11], permuted_tags[11] );
        }
      MB_TESSELLATOR_INCR_CASE_COUNT(7);
      output_tets.push( SimplexTemplateRefiner::templates + 545 );
      output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
      output_sign.push( 1 );
      MB_TESSELLATOR_INCR_SUBCASE_COUNT(7,0);
      switch ( comparison_bits )
        {
        case 5: // 5>4>3
          output_tets.push( SimplexTemplateRefiner::templates + 554 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(7,1);
          break;
        case 10: // 3>4>5
          output_tets.push( SimplexTemplateRefiner::templates + 554 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[13] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(7,2);
          break;
        case 6: // 3<4>5
          output_tets.push( SimplexTemplateRefiner::templates + 571 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(7,3);
          break;
        case 9: // 3>4<5
          output_tets.push( SimplexTemplateRefiner::templates + 588 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(7,4);
          break;
        case 14: // 3=4>5
          output_tets.push( SimplexTemplateRefiner::templates + 605 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(7,5);
          break;
        case 7: // 4=5,4>3
          output_tets.push( SimplexTemplateRefiner::templates + 605 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[13] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(7,6);
          break;
        case 13: // 5>4,3=4
          output_tets.push( SimplexTemplateRefiner::templates + 630 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(7,7);
          break;
        case 11: // 3>4=5
          output_tets.push( SimplexTemplateRefiner::templates + 630 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[13] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(7,8);
          break;
        case 15: // 3=4=5
          output_tets.push( SimplexTemplateRefiner::templates + 655 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(7,9);
          break;
        }
      break;
    case 9: // Ruprecht-Müller Case 4b
      comparison_bits = 
        ( permlen[1] <= permlen[2] ? 1 : 0 ) | ( permlen[1] >= permlen[2] ? 2 : 0 ) |
        ( permlen[2] <= permlen[3] ? 4 : 0 ) | ( permlen[2] >= permlen[3] ? 8 : 0 ) |
        ( permlen[3] <= permlen[4] ? 16 : 0 ) | ( permlen[3] >= permlen[4] ? 32 : 0 ) |
        ( permlen[1] <= permlen[4] ? 64 : 0 ) | ( permlen[1] >= permlen[4] ? 128 : 0 ) |
        0;
      if ( ( comparison_bits & 3 ) == 3 )
        {
        // Compute face point and tag
        for ( int i = 0; i < 6; ++ i )
          {
          permuted_coords[10][i] = ( permuted_coords[1][i] + permuted_coords[0][i] ) * .375 + permuted_coords[2][i] * .25;
          }
        (*this->tag_assigner)( permuted_tags[1], permuted_tags[0], permuted_tags[2], permuted_tags[10] );
        permuted_hash[10] = (*this->output_functor)(
          permuted_hash[1], permuted_hash[0], permuted_hash[2], permuted_coords[10], permuted_tags[10] );
        }
      if ( ( comparison_bits & 12 ) == 12 )
        {
        // Compute face point and tag
        for ( int i = 0; i < 6; ++ i )
          {
          permuted_coords[13][i] = ( permuted_coords[2][i] + permuted_coords[3][i] ) * .375 + permuted_coords[0][i] * .25;
          }
        (*this->tag_assigner)( permuted_tags[2], permuted_tags[3], permuted_tags[0], permuted_tags[13] );
        permuted_hash[13] = (*this->output_functor)(
          permuted_hash[2], permuted_hash[3], permuted_hash[0], permuted_coords[13], permuted_tags[13] );
        }
      if ( ( comparison_bits & 48 ) == 48 )
        {
        // Compute face point and tag
        for ( int i = 0; i < 6; ++ i )
          {
          permuted_coords[11][i] = ( permuted_coords[0][i] + permuted_coords[1][i] ) * .375 + permuted_coords[3][i] * .25;
          }
        (*this->tag_assigner)( permuted_tags[0], permuted_tags[1], permuted_tags[3], permuted_tags[11] );
        permuted_hash[11] = (*this->output_functor)(
          permuted_hash[0], permuted_hash[1], permuted_hash[3], permuted_coords[11], permuted_tags[11] );
        }
      if ( ( comparison_bits & 192 ) == 192 )
        {
        // Compute face point and tag
        for ( int i = 0; i < 6; ++ i )
          {
          permuted_coords[12][i] = ( permuted_coords[2][i] + permuted_coords[3][i] ) * .375 + permuted_coords[1][i] * .25;
          }
        (*this->tag_assigner)( permuted_tags[2], permuted_tags[3], permuted_tags[1], permuted_tags[12] );
        permuted_hash[12] = (*this->output_functor)(
          permuted_hash[2], permuted_hash[3], permuted_hash[1], permuted_coords[12], permuted_tags[12] );
        }
      MB_TESSELLATOR_INCR_CASE_COUNT(8);
      switch ( comparison_bits )
        {
        case 85: // 2>1,3>2,4>3,4>1
          output_tets.push( SimplexTemplateRefiner::templates + 688 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,0);
          break;
        case 102: // 1>2,3>2,3>4,4>1
          output_tets.push( SimplexTemplateRefiner::templates + 688 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,1);
          break;
        case 170: // 1>2,2>3,3>4,1>4
          output_tets.push( SimplexTemplateRefiner::templates + 688 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,2);
          break;
        case 153: // 2>1,2>3,4>3,1>4
          output_tets.push( SimplexTemplateRefiner::templates + 688 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,3);
          break;
        case 90: // 1>2,2>3,4>3,4>1
          output_tets.push( SimplexTemplateRefiner::templates + 688 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[9] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,4);
          break;
        case 105: // 2>1,2>3,3>4,4>1
          output_tets.push( SimplexTemplateRefiner::templates + 688 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[7] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,5);
          break;
        case 165: // 2>1,3>2,3>4,1>4
          output_tets.push( SimplexTemplateRefiner::templates + 688 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[19] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,6);
          break;
        case 150: // 1>2,3>2,4>3,1>4
          output_tets.push( SimplexTemplateRefiner::templates + 688 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[23] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,7);
          break;
        case 101: // 2>1,3>2,3>4,4>1
          {
          int alternates[] = { 713, 738, -1 };
          output_tets.push( SimplexTemplateRefiner::templates + this->best_tets( alternates, permuted_coords, 0, 1 ) );
          }
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,8);
          break;
        case 86: // 1>2,3>2,4>3,4>1
          {
          int alternates[] = {713, 738, -1 };
          output_tets.push( SimplexTemplateRefiner::templates + this->best_tets( alternates, permuted_coords, 14, -1 ) );
          }
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,9);
          break;
        case 154: // 1>2,2>3,4>3,1>4
          {
          int alternates[] = {713, 738, -1 };
          output_tets.push( SimplexTemplateRefiner::templates + this->best_tets( alternates, permuted_coords, 5, 1 ) );
          }
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,10);
          break;
        case 169: // 2>1,2>3,3>4,1>4
          {
          int alternates[] = {713, 738, -1 };
          output_tets.push( SimplexTemplateRefiner::templates + this->best_tets( alternates, permuted_coords, 15, -1 ) );
          }
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,11);
          break;
        case 89: // 2>1,2>3,4>3,4>1
          output_tets.push( SimplexTemplateRefiner::templates + 763 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,12);
          break;
        case 166: // 1>2,3>2,3>4,1>4
          output_tets.push( SimplexTemplateRefiner::templates + 763 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,13);
          break;
        case 103: // 1=2,3>2,3>4,4>1
          output_tets.push( SimplexTemplateRefiner::templates + 788 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,14);
          break;
        case 87: // 1=2,3>2,4>3,4>1
          output_tets.push( SimplexTemplateRefiner::templates + 788 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,15);
          break;
        case 185: // 2>1,2>3,3=4,1>4
          output_tets.push( SimplexTemplateRefiner::templates + 788 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,16);
          break;
        case 186: // 1>2,2>3,3=4,1>4
          output_tets.push( SimplexTemplateRefiner::templates + 788 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,17);
          break;
        case 158: // 1>2,2=3,4>3,1>4
          output_tets.push( SimplexTemplateRefiner::templates + 788 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[9] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,18);
          break;
        case 229: // 2>1,3>2,3>4,1=4
          output_tets.push( SimplexTemplateRefiner::templates + 788 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[7] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,19);
          break;
        case 233: // 2>1,2>3,3>4,1=4
          output_tets.push( SimplexTemplateRefiner::templates + 788 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[19] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,20);
          break;
        case 94: // 1>2,2=3,4>3,4>1
          output_tets.push( SimplexTemplateRefiner::templates + 788 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[23] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,21);
          break;
        case 155: // 1=2,2>3,4>3,1>4
          output_tets.push( SimplexTemplateRefiner::templates + 825 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,22);
          break;
        case 171: // 1=2,2>3,3>4,1>4
          output_tets.push( SimplexTemplateRefiner::templates + 825 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,23);
          break;
        case 118: // 1>2,3>2,3=4,4>1
          output_tets.push( SimplexTemplateRefiner::templates + 825 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,24);
          break;
        case 117: // 2>1,3>2,3=4,4>1
          output_tets.push( SimplexTemplateRefiner::templates + 825 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,25);
          break;
        case 109: // 2>1,2=3,3>4,4>1
          output_tets.push( SimplexTemplateRefiner::templates + 825 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[9] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,26);
          break;
        case 218: // 1>2,2>3,4>3,1=4
          output_tets.push( SimplexTemplateRefiner::templates + 825 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[7] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,27);
          break;
        case 214: // 1>2,3>2,4>3,1=4
          output_tets.push( SimplexTemplateRefiner::templates + 825 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[19] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,28);
          break;
        case 173: // 2>1,2=3,3>4,1>4
          output_tets.push( SimplexTemplateRefiner::templates + 825 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[23] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,29);
          break;
        case 91: // 1=2,2>3,4>3,4>1
          output_tets.push( SimplexTemplateRefiner::templates + 862 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,30);
          break;
        case 167: // 1=2,3>2,3>4,1>4
          output_tets.push( SimplexTemplateRefiner::templates + 862 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,31);
          break;
        case 182: // 1>2,3>2,3=4,1>4
          output_tets.push( SimplexTemplateRefiner::templates + 862 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,32);
          break;
        case 121: // 2>1,2>3,3=4,4>1
          output_tets.push( SimplexTemplateRefiner::templates + 862 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,33);
          break;
        case 93: // 2>1,2=3,4>3,4>1
          output_tets.push( SimplexTemplateRefiner::templates + 862 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[9] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,34);
          break;
        case 217: // 2>1,2>3,4>3,1=4
          output_tets.push( SimplexTemplateRefiner::templates + 862 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[7] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,35);
          break;
        case 230: // 1>2,3>2,3>4,1=4
          output_tets.push( SimplexTemplateRefiner::templates + 862 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[19] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,36);
          break;
        case 174: // 1>2,2=3,3>4,1>4
          output_tets.push( SimplexTemplateRefiner::templates + 862 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[23] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,37);
          break;
        case 119: // 1=2,3>2,3=4,4>1
          output_tets.push( SimplexTemplateRefiner::templates + 899 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,38);
          break;
        case 187: // 1=2>3=4,1>4
          output_tets.push( SimplexTemplateRefiner::templates + 899 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,39);
          break;
        case 222: // 1>2,2=3,4>3,1=4
          output_tets.push( SimplexTemplateRefiner::templates + 899 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[9] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,40);
          break;
        case 237: // 2>1,2=3,3>4,1=4
          output_tets.push( SimplexTemplateRefiner::templates + 899 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[7] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,41);
          break;
        case 95: // 4>1=2=3,4>3
          output_tets.push( SimplexTemplateRefiner::templates + 944 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,42);
          break;
        case 231: // 1=2,3>2,3>4,1=4
          output_tets.push( SimplexTemplateRefiner::templates + 944 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,43);
          break;
        case 190: // 1>2=3=4,1>4
          output_tets.push( SimplexTemplateRefiner::templates + 944 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,44);
          break;
        case 249: // 2>1,2>3,3=4,1=4
          output_tets.push( SimplexTemplateRefiner::templates + 944 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,45);
          break;
        case 175: // 1=2=3>4,1>4
          output_tets.push( SimplexTemplateRefiner::templates + 993 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,46);
          break;
        case 219: // 1=2>3,4>3,1=4
          output_tets.push( SimplexTemplateRefiner::templates + 993 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,47);
          break;
        case 125: // 2>1,2=3=4>1
          output_tets.push( SimplexTemplateRefiner::templates + 993 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,48);
          break;
        case 246: // 1>2,3>2,3=4=1
          output_tets.push( SimplexTemplateRefiner::templates + 993 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,49);
          break;
        case 255: // 1=2=3=4=1
          output_tets.push( SimplexTemplateRefiner::templates + 1042 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(8,50);
          break;
        }
      break;
    case 10: // Ruprecht-Müller Case 5
      comparison_bits = 
        ( permlen[1] <= permlen[2] ? 1 : 0 ) | ( permlen[1] >= permlen[2] ? 2 : 0 ) |
        ( permlen[3] <= permlen[4] ? 4 : 0 ) | ( permlen[3] >= permlen[4] ? 8 : 0 ) |
        0;
      if ( ( comparison_bits & 3 ) == 3 )
        {
        // Compute face point and tag
        for ( int i = 0; i < 6; ++ i )
          {
          permuted_coords[10][i] = ( permuted_coords[1][i] + permuted_coords[0][i] ) * .375 + permuted_coords[2][i] * .25;
          }
        (*this->tag_assigner)( permuted_tags[1], permuted_tags[0], permuted_tags[2], permuted_tags[10] );
        permuted_hash[10] = (*this->output_functor)(
          permuted_hash[1], permuted_hash[0], permuted_hash[2], permuted_coords[10], permuted_tags[10] );
        }
      if ( ( comparison_bits & 12 ) == 12 )
        {
        // Compute face point and tag
        for ( int i = 0; i < 6; ++ i )
          {
          permuted_coords[11][i] = ( permuted_coords[0][i] + permuted_coords[1][i] ) * .375 + permuted_coords[3][i] * .25;
          }
        (*this->tag_assigner)( permuted_tags[0], permuted_tags[1], permuted_tags[3], permuted_tags[11] );
        permuted_hash[11] = (*this->output_functor)(
          permuted_hash[0], permuted_hash[1], permuted_hash[3], permuted_coords[11], permuted_tags[11] );
        }
      MB_TESSELLATOR_INCR_CASE_COUNT(9);
      output_tets.push( SimplexTemplateRefiner::templates + 1107 );
      output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
      output_sign.push( 1 );
      MB_TESSELLATOR_INCR_SUBCASE_COUNT(9,0);
      switch ( comparison_bits )
        {
        case 10: // 1>2,3>4
          output_tets.push( SimplexTemplateRefiner::templates + 1116 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(9,1);
          break;
        case 5: // 2>1,4>3
          output_tets.push( SimplexTemplateRefiner::templates + 1116 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(9,2);
          break;
        case 6: // 1>2,4>3
          {
          int alternates[] = { 1137, 1158, -1 };
          output_tets.push( SimplexTemplateRefiner::templates + this->best_tets( alternates, permuted_coords, 0, 1 ) );
          }
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(9,3);
          break;
        case 9: // 2>1,3>4
          {
          int alternates[] = {1137, 1158, -1 };
          output_tets.push( SimplexTemplateRefiner::templates + this->best_tets( alternates, permuted_coords, 14, -1 ) );
          }
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(9,4);
          break;
        case 11: // 1=2,3>4
          {
          int alternates[] = { 1179, 1212, 1245, -1 };
          output_tets.push( SimplexTemplateRefiner::templates + this->best_tets( alternates, permuted_coords, 0, 1 ) );
          }
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(9,5);
          break;
        case 7: // 1=2,4>3
          {
          int alternates[] = {1179, 1212, 1245, -1 };
          output_tets.push( SimplexTemplateRefiner::templates + this->best_tets( alternates, permuted_coords, 14, -1 ) );
          }
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[14] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(9,6);
          break;
        case 14: // 3=4,1>2
          {
          int alternates[] = {1179, 1212, 1245, -1 };
          output_tets.push( SimplexTemplateRefiner::templates + this->best_tets( alternates, permuted_coords, 5, 1 ) );
          }
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[5] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(9,7);
          break;
        case 13: // 3=4,2>1
          {
          int alternates[] = {1179, 1212, 1245, -1 };
          output_tets.push( SimplexTemplateRefiner::templates + this->best_tets( alternates, permuted_coords, 15, -1 ) );
          }
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[15] );
          output_sign.push( -1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(9,8);
          break;
        case 15: // 1=2,3=4
          output_tets.push( SimplexTemplateRefiner::templates + 1278 );
          output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
          output_sign.push( 1 );
          MB_TESSELLATOR_INCR_SUBCASE_COUNT(9,9);
          break;
        }
      break;
    case 11: // Ruprecht-Müller Case 6
      MB_TESSELLATOR_INCR_CASE_COUNT(10);
      output_tets.push( SimplexTemplateRefiner::templates + 1319 );
      output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
      output_sign.push( 1 );
      MB_TESSELLATOR_INCR_SUBCASE_COUNT(10,0);
        {
        int alternates[] = { 1336, 1353, 1370, -1 };
        output_tets.push( SimplexTemplateRefiner::templates + this->best_tets( alternates, permuted_coords, 0, 1 ) );
        }
        output_perm.push( SimplexTemplateRefiner::permutations_from_index[0] );
        output_sign.push( 1 );
        MB_TESSELLATOR_INCR_SUBCASE_COUNT(10,1);
        break;
    }

  int* tets;
  int  ntets;
  int* perm;
  int  sgn;
#ifdef MB_DEBUG_TESSELLATOR
  if ( output_tets.empty() )
    {
    cout << "Argh! Case " << C << " Perm " << P << " has no output!" << endl;
    }
#endif // MB_DEBUG_TESSELLATOR
  while ( ! output_tets.empty() )
    {
    tets = output_tets.top();
    ntets = *tets;
    tets++;
    perm = output_perm.top();
    sgn = output_sign.top();

    output_tets.pop();
    output_perm.pop();
    output_sign.pop();

    int t;
    if ( sgn > 0 )
      {
      for ( t = 0; t < ntets; ++t )
        {
        this->refine_3_simplex( max_depth,
          permuted_coords[perm[tets[0]]], permuted_tags[perm[tets[0]]], permuted_hash[perm[tets[0]]],
          permuted_coords[perm[tets[1]]], permuted_tags[perm[tets[1]]], permuted_hash[perm[tets[1]]],
          permuted_coords[perm[tets[2]]], permuted_tags[perm[tets[2]]], permuted_hash[perm[tets[2]]],
          permuted_coords[perm[tets[3]]], permuted_tags[perm[tets[3]]], permuted_hash[perm[tets[3]]]
          );
        tets += 4;
        }
      }
    else
      {
      // we have an inverted tet... reverse the first 2 vertices
      // so the orientation is positive.
      for ( t = 0; t < ntets; ++t )
        {
        this->refine_3_simplex( max_depth,
          permuted_coords[perm[tets[1]]], permuted_tags[perm[tets[1]]], permuted_hash[perm[tets[1]]],
          permuted_coords[perm[tets[0]]], permuted_tags[perm[tets[0]]], permuted_hash[perm[tets[0]]],
          permuted_coords[perm[tets[2]]], permuted_tags[perm[tets[2]]], permuted_hash[perm[tets[2]]],
          permuted_coords[perm[tets[3]]], permuted_tags[perm[tets[3]]], permuted_hash[perm[tets[3]]]
        );
        tets += 4;
        }
      }
    }

  return true;
}
bool moab::SimplexTemplateRefiner::refine_entity ( EntityType  etyp,
EntityHandle  entity 
) [virtual]

Stream a single mesh entity through the refiner.

Implements moab::EntityRefiner.

Definition at line 46 of file SimplexTemplateRefiner.cpp.

{
  this->reset_heap_pointers();
  bool rval = true;
  const EntityHandle* conn;
  int num_nodes;
  Interface* imesh = this->tag_manager->get_input_mesh();
  if ( imesh->get_connectivity( entity, conn, num_nodes ) != MB_SUCCESS )
    {
    return false;
    }
  this->corner_coords.resize( 6 * num_nodes );
  this->corner_tags.resize( num_nodes );
  this->corner_handles.resize( num_nodes );

  // Have to make num_nodes calls to get_coords() because we need xyz interleaved with rst coords.
  Tag tag_handle;
  int tag_offset;
  void* tag_data;
  for ( int n = 0; n < num_nodes; ++ n )
    {
    if ( imesh->get_coords( &conn[n], 1, &corner_coords[6 * n + 3] ) != MB_SUCCESS )
      {
      return false;
      }
    tag_data = this->heap_tag_storage();
    for ( int i = 0; i < this->tag_manager->get_number_of_vertex_tags(); ++ i )
      {
      this->tag_manager->get_input_vertex_tag( i, tag_handle, tag_offset );
      if ( imesh->tag_get_data( tag_handle, &conn[n], 1, (char*)tag_data + tag_offset ) != MB_SUCCESS )
        {
        return false;
        }
      }
    if ( this->input_is_output )
      {
      this->corner_handles[n] = conn[n];
      }
    else
      {
      this->corner_handles[n] = this->output_functor->map_vertex( conn[n], &corner_coords[6 * n], tag_data );
#if 0
      std::cout << "#+# " << this->corner_handles[n] << " < "
        << corner_coords[ 6 * n + 3 ] << ", "
        << corner_coords[ 6 * n + 4 ] << ", "
        << corner_coords[ 6 * n + 5 ] << ">\n";
#endif // 0
      }
    this->corner_tags[n] = tag_data;
    }

  switch ( etyp )
    {
    case MBVERTEX:
      this->assign_parametric_coordinates( 1, MBVertexParametric, &this->corner_coords[0] );
      this->refine_0_simplex( &this->corner_coords[0], this->corner_tags[0], this->corner_handles[0] );
      rval = false;
      break;
    case MBEDGE:
      this->assign_parametric_coordinates( 2, MBEdgeParametric, &this->corner_coords[0] );
      rval = this->refine_1_simplex( this->maximum_number_of_subdivisions,
        &this->corner_coords[0], this->corner_tags[0], this->corner_handles[0],
        &this->corner_coords[6], this->corner_tags[1], this->corner_handles[1] );
      break;
    case MBTRI:
      this->assign_parametric_coordinates( 3, MBTriParametric, &this->corner_coords[0] );
      rval = this->refine_2_simplex( this->maximum_number_of_subdivisions, 7,
        &this->corner_coords[ 0], this->corner_tags[0], this->corner_handles[0],
        &this->corner_coords[ 6], this->corner_tags[1], this->corner_handles[1],
        &this->corner_coords[12], this->corner_tags[2], this->corner_handles[2] );
      break;
    case MBQUAD:
      std::cerr << "Quadrilaterals not handled yet\n";
      rval = false;
      break;
    case MBPOLYGON:
      std::cerr << "Polygons not handled yet\n";
      rval = false;
      break;
    case MBTET:
      this->assign_parametric_coordinates( 4, MBTetParametric, &this->corner_coords[0] );
      rval = this->refine_3_simplex( this->maximum_number_of_subdivisions,
        &this->corner_coords[ 0], this->corner_tags[0], this->corner_handles[0],
        &this->corner_coords[ 6], this->corner_tags[1], this->corner_handles[1],
        &this->corner_coords[12], this->corner_tags[2], this->corner_handles[2],
        &this->corner_coords[18], this->corner_tags[3], this->corner_handles[3]
      );
      break;
    case MBPYRAMID:
      std::cerr << "Pyramid schemes not handled yet\n";
      rval = false;
      break;
    case MBPRISM:
      std::cerr << "Prisms not handled yet\n";
      rval = false;
      break;
    case MBKNIFE:
      std::cerr << "Knifahedra not handled yet\n";
      rval = false;
      break;
    case MBHEX:
      std::cerr << "Hexahedra not handled yet\n";
      rval = false;
      break;
    case MBPOLYHEDRON:
      std::cerr << "Polyhedra not handled yet\n";
      rval = false;
      break;
    case MBENTITYSET:
      std::cerr <<
        "How should entity sets be handled? We might iterate over its entries or skip it."
        "Must coordinate with MeshRefiner's loop over entities...\n";
      rval = false;
      break;
    case MBMAXTYPE:
      rval = false;
      break;
    }
  return rval;
}

Set the function object used to decide which tag values an edge or face midpoint is assigned.

This will change the tag assigner's edge size evaluator to match the refiner's.

Parameters:
[in]taThe new tag assigner. This must be non-NULL.
Return values:
Trueif the tag assigner was changed and false otherwise.

Definition at line 173 of file SimplexTemplateRefiner.cpp.

{ 
  if ( ! ta || ta == this->tag_assigner )
    return false;

  this->tag_assigner = ta; 
  return true;
}

Member Data Documentation

std::vector<double> moab::SimplexTemplateRefiner::corner_coords [protected]

Definition at line 58 of file SimplexTemplateRefiner.hpp.

Definition at line 60 of file SimplexTemplateRefiner.hpp.

std::vector<void*> moab::SimplexTemplateRefiner::corner_tags [protected]

Definition at line 59 of file SimplexTemplateRefiner.hpp.

Definition at line 61 of file SimplexTemplateRefiner.hpp.

Definition at line 64 of file SimplexTemplateRefiner.hpp.

Definition at line 63 of file SimplexTemplateRefiner.hpp.

int moab::SimplexTemplateRefiner::templates [static, protected]

Definition at line 65 of file SimplexTemplateRefiner.hpp.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines