LCOV - code coverage report
Current view: top level - src - HigherOrderFactory.cpp (source / functions) Hit Total Coverage
Test: coverage_sk.info Lines: 346 430 80.5 %
Date: 2020-12-16 07:07:30 Functions: 22 28 78.6 %
Branches: 373 754 49.5 %

           Branch data     Line data    Source code
       1                 :            : /**
       2                 :            :  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
       3                 :            :  * storing and accessing finite element mesh data.
       4                 :            :  *
       5                 :            :  * Copyright 2004 Sandia Corporation.  Under the terms of Contract
       6                 :            :  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
       7                 :            :  * retains certain rights in this software.
       8                 :            :  *
       9                 :            :  * This library is free software; you can redistribute it and/or
      10                 :            :  * modify it under the terms of the GNU Lesser General Public
      11                 :            :  * License as published by the Free Software Foundation; either
      12                 :            :  * version 2.1 of the License, or (at your option) any later version.
      13                 :            :  *
      14                 :            :  */
      15                 :            : 
      16                 :            : #ifdef WIN32
      17                 :            : #ifdef _DEBUG
      18                 :            : // turn off warnings that say they debugging identifier has been truncated
      19                 :            : // this warning comes up when using some STL containers
      20                 :            : #pragma warning( disable : 4786 )
      21                 :            : #endif
      22                 :            : #endif
      23                 :            : 
      24                 :            : #include "moab/HigherOrderFactory.hpp"
      25                 :            : #include "SequenceManager.hpp"
      26                 :            : #include "UnstructuredElemSeq.hpp"
      27                 :            : #include "VertexSequence.hpp"
      28                 :            : #include "AEntityFactory.hpp"
      29                 :            : #include "moab/Core.hpp"
      30                 :            : #include "moab/CN.hpp"
      31                 :            : #include <assert.h>
      32                 :            : #include <algorithm>
      33                 :            : 
      34                 :            : namespace moab
      35                 :            : {
      36                 :            : 
      37                 :            : using namespace std;
      38                 :            : 
      39                 :          8 : HigherOrderFactory::HigherOrderFactory( Core* MB, Interface::HONodeAddedRemoved* function_object )
      40                 :          8 :     : mMB( MB ), mHONodeAddedRemoved( function_object )
      41                 :            : {
      42                 :          8 :     initialize_map();
      43                 :          8 : }
      44                 :          8 : HigherOrderFactory::~HigherOrderFactory() {}
      45                 :            : 
      46                 :            : // bool HigherOrderFactory::mMapInitialized = false;
      47                 :            : 
      48                 :          8 : void HigherOrderFactory::initialize_map()
      49                 :            : {
      50                 :            :     // if(mMapInitialized)
      51                 :            :     //  return;
      52                 :            : 
      53 [ +  - ][ +  + ]:        104 :     for( EntityType i = MBVERTEX; i < MBMAXTYPE; i++ )
      54                 :            :     {
      55                 :         96 :         const CN::ConnMap& canon_map     = CN::mConnectivityMap[i][0];
      56                 :         96 :         unsigned char( &this_map )[8][8] = mNodeMap[i];
      57         [ +  - ]:         96 :         int num_node                     = CN::VerticesPerEntity( i );
      58         [ +  + ]:        520 :         for( int j = 0; j < canon_map.num_sub_elements; j++ )
      59                 :            :         {
      60                 :        424 :             unsigned char x = canon_map.conn[j][0];
      61                 :        424 :             unsigned char y = canon_map.conn[j][1];
      62                 :        424 :             this_map[x][y]  = num_node;
      63                 :        424 :             this_map[y][x]  = num_node;
      64                 :        424 :             num_node++;
      65                 :            :         }
      66                 :            :     }
      67                 :            : 
      68                 :            :     // mMapInitialized = true;
      69                 :          8 : }
      70                 :            : 
      71                 :          8 : ErrorCode HigherOrderFactory::convert( const EntityHandle meshset, const bool mid_edge_nodes, const bool mid_face_nodes,
      72                 :            :                                        const bool mid_volume_nodes )
      73                 :            : {
      74         [ +  - ]:          8 :     Range entities;
      75         [ +  - ]:          8 :     mMB->get_entities_by_handle( meshset, entities, true );
      76         [ +  - ]:          8 :     return convert( entities, mid_edge_nodes, mid_face_nodes, mid_volume_nodes );
      77                 :            : }
      78                 :            : 
      79                 :          8 : ErrorCode HigherOrderFactory::convert( const Range& entities, const bool mid_edge_nodes, const bool mid_face_nodes,
      80                 :            :                                        const bool mid_volume_nodes )
      81                 :            : 
      82                 :            : {
      83                 :            : 
      84                 :            :     // TODO --  add some more code to prevent from splitting of entity sequences when we don't need
      85                 :            :     // to. Say we have all hex8's in our mesh and 3 falses are passed in.  In the end, no conversion
      86                 :            :     // will happen, but the sequences could still be split up.
      87                 :            : 
      88                 :            :     // find out what entity sequences we need to convert
      89                 :            :     // and where, if necessary, to split them
      90                 :            : 
      91         [ +  - ]:          8 :     SequenceManager* seq_manager = mMB->sequence_manager();
      92         [ +  - ]:          8 :     Range::const_pair_iterator p_iter;
      93 [ +  - ][ +  - ]:         17 :     for( p_iter = entities.const_pair_begin(); p_iter != entities.const_pair_end(); ++p_iter )
         [ +  - ][ +  - ]
                 [ +  + ]
      94                 :            :     {
      95                 :            : 
      96         [ +  - ]:          9 :         EntityHandle h = p_iter->first;
      97 [ +  - ][ +  + ]:         22 :         while( h <= p_iter->second )
      98                 :            :         {
      99                 :            : 
     100                 :            :             EntitySequence* seq;
     101         [ +  - ]:         13 :             ErrorCode rval = seq_manager->find( h, seq );
     102         [ -  + ]:         13 :             if( MB_SUCCESS != rval ) return rval;
     103                 :            : 
     104 [ +  - ][ +  - ]:         13 :             if( seq->type() == MBVERTEX || seq->type() >= MBENTITYSET ) return MB_TYPE_OUT_OF_RANGE;
         [ +  - ][ -  + ]
                 [ -  + ]
     105                 :            : 
     106                 :            :             // make sequence is not structured mesh
     107                 :         13 :             ElementSequence* elemseq = static_cast< ElementSequence* >( seq );
     108 [ +  - ][ -  + ]:         13 :             if( NULL == elemseq->get_connectivity_array() ) return MB_NOT_IMPLEMENTED;
     109                 :            : 
     110         [ +  - ]:         13 :             EntityHandle last = p_iter->second;
     111 [ +  - ][ +  + ]:         13 :             if( last > seq->end_handle() ) last = seq->end_handle();
                 [ +  - ]
     112                 :            : 
     113         [ +  - ]:         13 :             rval = convert_sequence( elemseq, h, last, mid_edge_nodes, mid_face_nodes, mid_volume_nodes );
     114         [ -  + ]:         13 :             if( MB_SUCCESS != rval ) return rval;
     115                 :            : 
     116                 :         13 :             h = last + 1;
     117                 :            :         }
     118                 :            :     }
     119                 :            : 
     120                 :          8 :     return MB_SUCCESS;
     121                 :            : }
     122                 :            : 
     123                 :         13 : ErrorCode HigherOrderFactory::convert_sequence( ElementSequence* seq, EntityHandle start, EntityHandle end,
     124                 :            :                                                 bool mid_edge_nodes, bool mid_face_nodes, bool mid_volume_nodes )
     125                 :            : {
     126                 :            : 
     127                 :         13 :     ErrorCode status = MB_SUCCESS;
     128                 :            : 
     129                 :            :     // lets make sure parameters are ok before we continue
     130         [ +  - ]:         13 :     switch( seq->type() )
           [ -  -  +  + ]
     131                 :            :     {
     132                 :            :         default:
     133                 :          0 :             return MB_TYPE_OUT_OF_RANGE;
     134                 :            :         case MBEDGE:
     135                 :          0 :             mid_face_nodes = false;
     136                 :            :         case MBTRI:
     137                 :            :         case MBQUAD:
     138                 :          2 :             mid_volume_nodes = false;
     139                 :            :         case MBTET:
     140                 :            :         case MBHEX:
     141                 :            :         case MBPRISM:
     142                 :            :         case MBPYRAMID:
     143                 :            :         case MBKNIFE:
     144                 :         13 :             break;
     145                 :            :     }
     146                 :            : 
     147                 :            :     // calculate number of nodes in target configuration
     148 [ +  - ][ +  - ]:         13 :     unsigned nodes_per_elem = CN::VerticesPerEntity( seq->type() );
     149 [ +  + ][ +  - ]:         13 :     if( mid_edge_nodes ) nodes_per_elem += ( seq->type() == MBEDGE ) ? 1 : CN::NumSubEntities( seq->type(), 1 );
         [ +  - ][ +  - ]
                 [ +  - ]
     150         [ +  + ]:         13 :     if( mid_face_nodes )
     151 [ +  - ][ +  - ]:          6 :         nodes_per_elem += ( CN::Dimension( seq->type() ) == 2 ) ? 1 : CN::NumSubEntities( seq->type(), 2 );
         [ +  + ][ +  - ]
                 [ +  - ]
     152         [ +  + ]:         13 :     if( mid_volume_nodes ) nodes_per_elem += 1;
     153                 :            : 
     154 [ +  - ][ -  + ]:         13 :     if( nodes_per_elem == seq->nodes_per_element() ) return MB_SUCCESS;
     155                 :            : 
     156                 :            :     Tag deletable_nodes;
     157         [ +  - ]:         13 :     status = mMB->tag_get_handle( 0, 1, MB_TYPE_BIT, deletable_nodes, MB_TAG_CREAT | MB_TAG_BIT );
     158         [ -  + ]:         13 :     if( MB_SUCCESS != status ) return status;
     159                 :            : 
     160 [ +  - ][ +  - ]:         13 :     UnstructuredElemSeq* new_seq = new UnstructuredElemSeq( start, end - start + 1, nodes_per_elem, end - start + 1 );
     161                 :            : 
     162         [ +  - ]:         13 :     copy_corner_nodes( seq, new_seq );
     163                 :            : 
     164 [ +  - ][ +  + ]:         13 :     if( seq->has_mid_edge_nodes() && mid_edge_nodes )
         [ -  + ][ -  + ]
     165         [ #  # ]:          0 :         status = copy_mid_edge_nodes( seq, new_seq );
     166 [ +  - ][ +  + ]:         13 :     else if( seq->has_mid_edge_nodes() && !mid_edge_nodes )
         [ +  - ][ +  + ]
     167         [ +  - ]:          2 :         status = remove_mid_edge_nodes( seq, start, end, deletable_nodes );
     168 [ +  - ][ +  - ]:         11 :     else if( !seq->has_mid_edge_nodes() && mid_edge_nodes )
         [ +  + ][ +  + ]
     169         [ +  - ]:          8 :         status = zero_mid_edge_nodes( new_seq );
     170         [ -  + ]:         13 :     if( MB_SUCCESS != status ) return status;
     171                 :            : 
     172 [ +  - ][ -  + ]:         13 :     if( seq->has_mid_face_nodes() && mid_face_nodes )
         [ #  # ][ -  + ]
     173         [ #  # ]:          0 :         status = copy_mid_face_nodes( seq, new_seq );
     174 [ +  - ][ -  + ]:         13 :     else if( seq->has_mid_face_nodes() && !mid_face_nodes )
         [ #  # ][ -  + ]
     175         [ #  # ]:          0 :         status = remove_mid_face_nodes( seq, start, end, deletable_nodes );
     176 [ +  - ][ +  - ]:         13 :     else if( !seq->has_mid_face_nodes() && mid_face_nodes )
         [ +  + ][ +  + ]
     177         [ +  - ]:          6 :         status = zero_mid_face_nodes( new_seq );
     178         [ -  + ]:         13 :     if( MB_SUCCESS != status )
     179                 :            :     {
     180         [ #  # ]:          0 :         mMB->tag_delete( deletable_nodes );
     181                 :          0 :         return status;
     182                 :            :     }
     183                 :            : 
     184 [ +  - ][ -  + ]:         13 :     if( seq->has_mid_volume_nodes() && mid_volume_nodes )
         [ #  # ][ -  + ]
     185         [ #  # ]:          0 :         status = copy_mid_volume_nodes( seq, new_seq );
     186 [ +  - ][ -  + ]:         13 :     else if( seq->has_mid_volume_nodes() && !mid_volume_nodes )
         [ #  # ][ -  + ]
     187         [ #  # ]:          0 :         status = remove_mid_volume_nodes( seq, start, end, deletable_nodes );
     188 [ +  - ][ +  - ]:         13 :     else if( !seq->has_mid_volume_nodes() && mid_volume_nodes )
         [ +  + ][ +  + ]
     189         [ +  - ]:          4 :         status = zero_mid_volume_nodes( new_seq );
     190         [ -  + ]:         13 :     if( MB_SUCCESS != status )
     191                 :            :     {
     192         [ #  # ]:          0 :         mMB->tag_delete( deletable_nodes );
     193                 :          0 :         return status;
     194                 :            :     }
     195                 :            : 
     196                 :            :     // gather nodes that were marked
     197         [ +  - ]:         13 :     Range nodes;
     198         [ +  - ]:         13 :     mMB->get_entities_by_type_and_tag( 0, MBVERTEX, &deletable_nodes, NULL, 1, nodes );
     199                 :            : 
     200                 :            :     // EntityHandle low_meshset;
     201                 :            :     // int dum;
     202                 :            :     // low_meshset = CREATE_HANDLE(MBENTITYSET, 0, dum);
     203                 :            : 
     204 [ +  - ][ +  - ]:        394 :     for( Range::iterator iter = nodes.begin(); iter != nodes.end(); ++iter )
         [ +  - ][ +  - ]
                 [ +  + ]
     205                 :            :     {
     206                 :        381 :         unsigned char marked = 0;
     207 [ +  - ][ +  - ]:        381 :         mMB->tag_get_data( deletable_nodes, &( *iter ), 1, &marked );
     208         [ +  + ]:        381 :         if( marked )
     209                 :            :         {
     210                 :            :             // we can delete it
     211 [ -  + ][ #  # ]:        177 :             if( mHONodeAddedRemoved ) mHONodeAddedRemoved->node_removed( *iter );
                 [ #  # ]
     212 [ +  - ][ +  - ]:        177 :             mMB->delete_entities( &( *iter ), 1 );
     213                 :            :         }
     214                 :            :     }
     215                 :            : 
     216 [ +  - ][ +  + ]:         13 :     const bool create_midedge = !seq->has_mid_edge_nodes() && mid_edge_nodes;
                 [ +  + ]
     217 [ +  - ][ +  - ]:         13 :     const bool create_midface = !seq->has_mid_face_nodes() && mid_face_nodes;
                 [ +  + ]
     218 [ +  - ][ +  - ]:         13 :     const bool create_midvolm = !seq->has_mid_volume_nodes() && mid_volume_nodes;
                 [ +  + ]
     219                 :            : 
     220         [ +  - ]:         13 :     mMB->tag_delete( deletable_nodes );
     221                 :            : 
     222 [ +  - ][ +  - ]:         13 :     status = mMB->sequence_manager()->replace_subsequence( new_seq );
     223         [ -  + ]:         13 :     if( MB_SUCCESS != status )
     224                 :            :     {
     225         [ #  # ]:          0 :         SequenceData* data = new_seq->data();
     226         [ #  # ]:          0 :         delete new_seq;
     227         [ #  # ]:          0 :         delete data;
     228                 :          0 :         return status;
     229                 :            :     }
     230                 :            : 
     231         [ +  + ]:         13 :     if( create_midedge )
     232                 :            :     {
     233         [ +  - ]:          8 :         status = add_mid_edge_nodes( new_seq );
     234         [ -  + ]:          8 :         if( MB_SUCCESS != status ) return status;
     235                 :            :     }
     236         [ +  + ]:         13 :     if( create_midface )
     237                 :            :     {
     238         [ +  - ]:          6 :         status = add_mid_face_nodes( new_seq );
     239         [ -  + ]:          6 :         if( MB_SUCCESS != status ) return status;
     240                 :            :     }
     241         [ +  + ]:         13 :     if( create_midvolm )
     242                 :            :     {
     243         [ +  - ]:          4 :         status = add_mid_volume_nodes( new_seq );
     244         [ -  + ]:          4 :         if( MB_SUCCESS != status ) return status;
     245                 :            :     }
     246                 :            : 
     247                 :         13 :     return status;
     248                 :            : }
     249                 :            : 
     250                 :          4 : ErrorCode HigherOrderFactory::add_mid_volume_nodes( ElementSequence* seq )
     251                 :            : {
     252                 :          4 :     EntityType this_type         = seq->type();
     253                 :          4 :     SequenceManager* seq_manager = mMB->sequence_manager();
     254                 :            : 
     255                 :            :     // find out where in the connectivity list to add these new mid volume nodes
     256         [ +  + ]:          4 :     int edge_factor = seq->has_mid_edge_nodes() ? 1 : 0;
     257         [ +  + ]:          4 :     int face_factor = seq->has_mid_face_nodes() ? 1 : 0;
     258                 :            :     // offset by number of higher order nodes on edges if they exist
     259                 :          4 :     int num_corner_nodes = CN::VerticesPerEntity( this_type );
     260                 :          4 :     int new_node_index   = num_corner_nodes;
     261                 :          4 :     new_node_index += edge_factor * CN::mConnectivityMap[this_type][0].num_sub_elements;
     262                 :          4 :     new_node_index += face_factor * CN::mConnectivityMap[this_type][1].num_sub_elements;
     263                 :            : 
     264                 :          4 :     EntityHandle* element     = seq->get_connectivity_array();
     265                 :          4 :     EntityHandle curr_handle  = seq->start_handle();
     266                 :          4 :     int nodes_per_element     = seq->nodes_per_element();
     267                 :          4 :     EntityHandle* end_element = element + nodes_per_element * ( seq->size() );
     268                 :            : 
     269                 :            :     // iterate over the elements
     270         [ +  + ]:         36 :     for( ; element < end_element; element += nodes_per_element )
     271                 :            :     {
     272                 :            :         // find the centroid of this element
     273                 :         32 :         double tmp_coords[3], sum_coords[3] = { 0, 0, 0 };
     274                 :         32 :         EntitySequence* eseq = NULL;
     275         [ +  + ]:        288 :         for( int i = 0; i < num_corner_nodes; i++ )
     276                 :            :         {
     277         [ +  - ]:        256 :             seq_manager->find( element[i], eseq );
     278                 :        256 :             static_cast< VertexSequence* >( eseq )->get_coordinates( element[i], tmp_coords[0], tmp_coords[1],
     279         [ +  - ]:        256 :                                                                      tmp_coords[2] );
     280                 :        256 :             sum_coords[0] += tmp_coords[0];
     281                 :        256 :             sum_coords[1] += tmp_coords[1];
     282                 :        256 :             sum_coords[2] += tmp_coords[2];
     283                 :            :         }
     284                 :         32 :         sum_coords[0] /= num_corner_nodes;
     285                 :         32 :         sum_coords[1] /= num_corner_nodes;
     286                 :         32 :         sum_coords[2] /= num_corner_nodes;
     287                 :            : 
     288                 :            :         // create a new vertex at the centroid
     289         [ +  - ]:         32 :         mMB->create_vertex( sum_coords, element[new_node_index] );
     290                 :            : 
     291 [ +  + ][ +  - ]:         32 :         if( mHONodeAddedRemoved ) mHONodeAddedRemoved->node_added( element[new_node_index], curr_handle );
     292                 :            : 
     293                 :         32 :         curr_handle++;
     294                 :            :     }
     295                 :            : 
     296                 :          4 :     return MB_SUCCESS;
     297                 :            : }
     298                 :            : 
     299                 :          6 : ErrorCode HigherOrderFactory::add_mid_face_nodes( ElementSequence* seq )
     300                 :            : {
     301         [ +  - ]:          6 :     EntityType this_type         = seq->type();
     302         [ +  - ]:          6 :     SequenceManager* seq_manager = mMB->sequence_manager();
     303         [ +  - ]:          6 :     int num_vertices             = CN::VerticesPerEntity( this_type );
     304                 :          6 :     int num_edges                = CN::mConnectivityMap[this_type][0].num_sub_elements;
     305 [ +  - ][ +  + ]:          6 :     num_edges                    = seq->has_mid_edge_nodes() ? num_edges : 0;
     306                 :          6 :     int num_faces                = CN::mConnectivityMap[this_type][1].num_sub_elements;
     307                 :            : 
     308                 :          6 :     const CN::ConnMap& entity_faces = CN::mConnectivityMap[this_type][1];
     309                 :            : 
     310         [ +  - ]:          6 :     EntityHandle* element     = seq->get_connectivity_array();
     311         [ +  - ]:          6 :     EntityHandle curr_handle  = seq->start_handle();
     312         [ +  - ]:          6 :     int nodes_per_element     = seq->nodes_per_element();
     313         [ +  - ]:          6 :     EntityHandle* end_element = element + nodes_per_element * ( seq->size() );
     314                 :            : 
     315                 :            :     EntityHandle tmp_face_conn[4];  // max face nodes = 4
     316         [ +  - ]:          6 :     std::vector< EntityHandle > adjacent_entities( 4 );
     317                 :            : 
     318                 :            :     double tmp_coords[3];
     319                 :            : 
     320                 :            :     // iterate over the elements
     321         [ +  + ]:         98 :     for( ; element < end_element; element += nodes_per_element )
     322                 :            :     {
     323                 :            :         // for each edge in this entity
     324         [ +  + ]:        396 :         for( int i = 0; i < num_faces; i++ )
     325                 :            :         {
     326                 :            :             // a node was already assigned
     327         [ -  + ]:        304 :             if( element[i + num_edges + num_vertices] != 0 ) continue;
     328                 :            : 
     329                 :        304 :             tmp_face_conn[0] = element[entity_faces.conn[i][0]];
     330                 :        304 :             tmp_face_conn[1] = element[entity_faces.conn[i][1]];
     331                 :        304 :             tmp_face_conn[2] = element[entity_faces.conn[i][2]];
     332         [ +  + ]:        304 :             if( entity_faces.num_corners_per_sub_element[i] == 4 )
     333                 :         96 :                 tmp_face_conn[3] = element[entity_faces.conn[i][3]];
     334                 :            :             else
     335                 :        208 :                 tmp_face_conn[3] = 0;
     336                 :            : 
     337         [ +  - ]:        304 :             EntityHandle already_made_node = center_node_exist( tmp_face_conn, adjacent_entities );
     338                 :            : 
     339         [ +  + ]:        304 :             if( already_made_node ) { element[i + num_edges + num_vertices] = already_made_node; }
     340                 :            :             // create a node
     341                 :            :             else
     342                 :            :             {
     343                 :        249 :                 EntitySequence* tmp_sequence = NULL;
     344                 :        249 :                 double sum_coords[3]         = { 0, 0, 0 };
     345                 :        249 :                 int max_nodes                = entity_faces.num_corners_per_sub_element[i];
     346         [ +  + ]:       1089 :                 for( int k = 0; k < max_nodes; k++ )
     347                 :            :                 {
     348         [ +  - ]:        840 :                     seq_manager->find( tmp_face_conn[k], tmp_sequence );
     349                 :            :                     static_cast< VertexSequence* >( tmp_sequence )
     350         [ +  - ]:        840 :                         ->get_coordinates( tmp_face_conn[k], tmp_coords[0], tmp_coords[1], tmp_coords[2] );
     351                 :        840 :                     sum_coords[0] += tmp_coords[0];
     352                 :        840 :                     sum_coords[1] += tmp_coords[1];
     353                 :        840 :                     sum_coords[2] += tmp_coords[2];
     354                 :            :                 }
     355                 :            : 
     356                 :        249 :                 sum_coords[0] /= max_nodes;
     357                 :        249 :                 sum_coords[1] /= max_nodes;
     358                 :        249 :                 sum_coords[2] /= max_nodes;
     359                 :            : 
     360         [ +  - ]:        249 :                 mMB->create_vertex( sum_coords, element[i + num_edges + num_vertices] );
     361                 :            :             }
     362                 :            : 
     363         [ -  + ]:        304 :             if( mHONodeAddedRemoved )
     364         [ #  # ]:          0 :                 mHONodeAddedRemoved->node_added( element[i + num_edges + num_vertices], curr_handle );
     365                 :            :         }
     366                 :            : 
     367                 :         92 :         curr_handle++;
     368                 :            :     }
     369                 :            : 
     370                 :          6 :     return MB_SUCCESS;
     371                 :            : }
     372                 :            : 
     373                 :          8 : ErrorCode HigherOrderFactory::add_mid_edge_nodes( ElementSequence* seq )
     374                 :            : {
     375                 :            :     // for each node, need to see if it was already created.
     376         [ +  - ]:          8 :     EntityType this_type         = seq->type();
     377         [ +  - ]:          8 :     SequenceManager* seq_manager = mMB->sequence_manager();
     378                 :            : 
     379                 :            :     // offset by number of corner nodes
     380         [ +  - ]:          8 :     int num_vertices = CN::VerticesPerEntity( this_type );
     381                 :          8 :     int num_edges    = CN::mConnectivityMap[this_type][0].num_sub_elements;
     382                 :            : 
     383                 :          8 :     const CN::ConnMap& entity_edges = CN::mConnectivityMap[this_type][0];
     384                 :            : 
     385         [ +  - ]:          8 :     EntityHandle* element     = seq->get_connectivity_array();
     386         [ +  - ]:          8 :     EntityHandle curr_handle  = seq->start_handle();
     387         [ +  - ]:          8 :     int nodes_per_element     = seq->nodes_per_element();
     388         [ +  - ]:          8 :     EntityHandle* end_element = element + nodes_per_element * ( seq->size() );
     389                 :            : 
     390                 :            :     EntityHandle tmp_edge_conn[2];
     391         [ +  - ]:          8 :     std::vector< EntityHandle > adjacent_entities( 32 );
     392                 :            : 
     393                 :            :     double tmp_coords[3];
     394                 :            : 
     395                 :            :     // iterate over the elements
     396         [ +  + ]:        116 :     for( ; element < end_element; element += nodes_per_element )
     397                 :            :     {
     398                 :            :         // for each edge in this entity
     399         [ +  + ]:        852 :         for( int i = 0; i < num_edges; i++ )
     400                 :            :         {
     401                 :            :             // a node was already assigned
     402         [ -  + ]:        744 :             if( element[i + num_vertices] != 0 ) continue;
     403                 :            : 
     404                 :        744 :             tmp_edge_conn[0] = element[entity_edges.conn[i][0]];
     405                 :        744 :             tmp_edge_conn[1] = element[entity_edges.conn[i][1]];
     406                 :            : 
     407         [ +  - ]:        744 :             EntityHandle already_made_node = center_node_exist( tmp_edge_conn[0], tmp_edge_conn[1], adjacent_entities );
     408                 :            : 
     409         [ +  + ]:        744 :             if( already_made_node ) { element[i + num_vertices] = already_made_node; }
     410                 :            :             // create a node
     411                 :            :             else
     412                 :            :             {
     413                 :        522 :                 EntitySequence* tmp_sequence = NULL;
     414                 :        522 :                 double sum_coords[3]         = { 0, 0, 0 };
     415         [ +  - ]:        522 :                 seq_manager->find( tmp_edge_conn[0], tmp_sequence );
     416                 :            :                 static_cast< VertexSequence* >( tmp_sequence )
     417         [ +  - ]:        522 :                     ->get_coordinates( tmp_edge_conn[0], tmp_coords[0], tmp_coords[1], tmp_coords[2] );
     418                 :        522 :                 sum_coords[0] += tmp_coords[0];
     419                 :        522 :                 sum_coords[1] += tmp_coords[1];
     420                 :        522 :                 sum_coords[2] += tmp_coords[2];
     421         [ +  - ]:        522 :                 seq_manager->find( tmp_edge_conn[1], tmp_sequence );
     422                 :            :                 static_cast< VertexSequence* >( tmp_sequence )
     423         [ +  - ]:        522 :                     ->get_coordinates( tmp_edge_conn[1], tmp_coords[0], tmp_coords[1], tmp_coords[2] );
     424                 :        522 :                 sum_coords[0] = ( sum_coords[0] + tmp_coords[0] ) / 2;
     425                 :        522 :                 sum_coords[1] = ( sum_coords[1] + tmp_coords[1] ) / 2;
     426                 :        522 :                 sum_coords[2] = ( sum_coords[2] + tmp_coords[2] ) / 2;
     427                 :            : 
     428         [ +  - ]:        522 :                 mMB->create_vertex( sum_coords, element[i + num_vertices] );
     429                 :            :             }
     430                 :            : 
     431 [ -  + ][ #  # ]:        744 :             if( mHONodeAddedRemoved ) mHONodeAddedRemoved->node_added( element[i + num_vertices], curr_handle );
     432                 :            :         }
     433                 :            : 
     434                 :        108 :         curr_handle++;
     435                 :            :     }
     436                 :            : 
     437                 :          8 :     return MB_SUCCESS;
     438                 :            : }
     439                 :            : 
     440                 :        744 : EntityHandle HigherOrderFactory::center_node_exist( EntityHandle corner1, EntityHandle corner2,
     441                 :            :                                                     std::vector< EntityHandle >& adj_entities )
     442                 :            : {
     443         [ +  - ]:        744 :     AEntityFactory* a_fact = mMB->a_entity_factory();
     444         [ +  - ]:        744 :     std::vector< EntityHandle > adj_corner1( 32 );
     445         [ +  - ]:       1488 :     std::vector< EntityHandle > adj_corner2( 32 );
     446                 :            : 
     447                 :            :     // create needed vertex adjacencies
     448 [ +  - ][ +  + ]:        744 :     if( !a_fact->vert_elem_adjacencies() ) a_fact->create_vert_elem_adjacencies();
                 [ +  - ]
     449                 :            : 
     450                 :            :     // vectors are returned sorted
     451                 :            : 
     452         [ +  - ]:        744 :     a_fact->get_adjacencies( corner1, adj_corner1 );
     453         [ +  - ]:        744 :     a_fact->get_adjacencies( corner2, adj_corner2 );
     454                 :            : 
     455                 :            :     // these are the entities adjacent to both nodes
     456                 :        744 :     adj_entities.clear();
     457                 :            :     std::set_intersection( adj_corner1.begin(), adj_corner1.end(), adj_corner2.begin(), adj_corner2.end(),
     458 [ +  - ][ +  - ]:        744 :                            std::back_inserter< std::vector< EntityHandle > >( adj_entities ) );
     459                 :            : 
     460                 :            :     // iterate of the entities to find a mid node
     461                 :            :     const EntityHandle* conn;
     462                 :        744 :     int conn_size = 0;
     463 [ +  - ][ +  + ]:       1534 :     for( std::vector< EntityHandle >::iterator iter = adj_entities.begin(); iter != adj_entities.end(); )
     464                 :            :     {
     465 [ +  - ][ +  - ]:       1012 :         EntityType this_type = TYPE_FROM_HANDLE( *iter );
     466         [ +  + ]:       1012 :         if( this_type == MBENTITYSET )
     467                 :            :         {
     468         [ +  - ]:         78 :             ++iter;
     469                 :         78 :             continue;
     470                 :            :         }
     471 [ +  - ][ +  - ]:        934 :         mMB->get_connectivity( *iter, conn, conn_size );
     472                 :            :         // if this entity has mid edge nodes
     473 [ +  - ][ +  + ]:        934 :         if( CN::HasMidEdgeNodes( this_type, conn_size ) )
     474                 :            :         {
     475                 :            :             // find out at which index the mid node should be at
     476         [ +  - ]:        602 :             int first_node  = std::find( conn, conn + conn_size, corner1 ) - conn;
     477         [ +  - ]:        602 :             int second_node = std::find( conn, conn + conn_size, corner2 ) - conn;
     478 [ +  - ][ -  + ]:        602 :             if( first_node == conn_size || second_node == conn_size )
     479                 :          0 :                 assert( "We should always find our nodes no matter what" == NULL );
     480                 :        602 :             int high_node_index = mNodeMap[this_type][first_node][second_node];
     481         [ +  + ]:        602 :             if( conn[high_node_index] != 0 ) return conn[high_node_index];
     482         [ +  - ]:        380 :             ++iter;
     483                 :            :         }
     484                 :            :         else
     485                 :            :         {
     486         [ +  - ]:        332 :             iter = adj_entities.erase( iter );
     487                 :            :         }
     488                 :            :     }
     489                 :            : 
     490                 :       1266 :     return 0;
     491                 :            : }
     492                 :            : 
     493                 :        304 : EntityHandle HigherOrderFactory::center_node_exist( EntityHandle corners[4], std::vector< EntityHandle >& adj_entities )
     494                 :            : {
     495         [ +  - ]:        304 :     AEntityFactory* a_fact = mMB->a_entity_factory();
     496 [ +  - ][ +  + ]:       2736 :     std::vector< EntityHandle > adj_corner[4];
                 [ #  # ]
     497         [ +  + ]:        304 :     int num_nodes = corners[3] == 0 ? 3 : 4;
     498                 :        304 :     int i         = 0;
     499                 :            : 
     500                 :            :     // create needed vertex adjacencies
     501 [ +  - ][ -  + ]:        304 :     if( !a_fact->vert_elem_adjacencies() ) a_fact->create_vert_elem_adjacencies();
                 [ #  # ]
     502                 :            : 
     503                 :            :     // vectors are returned sorted
     504         [ +  + ]:       1312 :     for( i = 0; i < num_nodes; i++ )
     505         [ +  - ]:       1008 :         a_fact->get_adjacencies( corners[i], adj_corner[i] );
     506                 :            : 
     507                 :            :     // these are the entities adjacent to both nodes
     508         [ +  + ]:       1008 :     for( i = 1; i < num_nodes; i++ )
     509                 :            :     {
     510                 :        704 :         adj_entities.clear();
     511                 :       1408 :         std::set_intersection( adj_corner[i - 1].begin(), adj_corner[i - 1].end(), adj_corner[i].begin(),
     512 [ +  - ][ +  - ]:        704 :                                adj_corner[i].end(), std::back_inserter< std::vector< EntityHandle > >( adj_entities ) );
     513                 :        704 :         adj_corner[i].swap( adj_entities );
     514                 :            :     }
     515                 :        304 :     adj_entities.swap( adj_corner[i - 1] );
     516                 :            : 
     517                 :            :     // iterate of the entities to find a mid node
     518                 :            :     const EntityHandle* conn;
     519                 :        304 :     int conn_size = 0;
     520 [ +  - ][ +  + ]:        622 :     for( std::vector< EntityHandle >::iterator iter = adj_entities.begin(); iter != adj_entities.end(); )
     521                 :            :     {
     522 [ +  - ][ +  - ]:        373 :         EntityType this_type = TYPE_FROM_HANDLE( *iter );
     523         [ +  + ]:        373 :         if( this_type == MBENTITYSET )
     524                 :            :         {
     525         [ +  - ]:         36 :             ++iter;
     526                 :         36 :             continue;
     527                 :            :         }
     528                 :        337 :         const CN::ConnMap& entity_faces = CN::mConnectivityMap[this_type][1];
     529 [ +  - ][ +  - ]:        337 :         mMB->get_connectivity( *iter, conn, conn_size );
     530         [ +  - ]:        337 :         int offset = CN::VerticesPerEntity( this_type );
     531 [ +  - ][ +  + ]:        337 :         if( CN::HasMidEdgeNodes( this_type, conn_size ) ) offset += CN::mConnectivityMap[this_type][0].num_sub_elements;
     532                 :            : 
     533                 :            :         // if this entity has mid face nodes
     534 [ +  - ][ +  + ]:        337 :         if( CN::HasMidFaceNodes( this_type, conn_size ) )
     535                 :            :         {
     536                 :            :             int k;
     537                 :            :             int indexes[4];
     538         [ +  + ]:       1085 :             for( k = 0; k < num_nodes; k++ )
     539         [ +  - ]:        816 :                 indexes[k] = std::find( conn, conn + conn_size, corners[k] ) - conn;
     540                 :            : 
     541                 :            :             // find out at which index the mid node should be at
     542         [ +  + ]:        854 :             for( k = 0; k < entity_faces.num_sub_elements; k++ )
     543                 :            :             {
     544 [ +  - ][ -  + ]:        640 :                 if( CN::VerticesPerEntity( entity_faces.target_type[k] ) != num_nodes ) continue;
     545                 :            : 
     546         [ +  - ]:        640 :                 int* pivot = std::find( indexes, indexes + num_nodes, entity_faces.conn[k][0] );
     547         [ +  + ]:        640 :                 if( pivot == indexes + num_nodes ) continue;
     548                 :            : 
     549 [ +  + ][ +  - ]:        506 :                 if( pivot != indexes ) std::rotate( indexes, pivot, indexes + num_nodes );
     550                 :            : 
     551 [ +  - ][ +  + ]:        506 :                 if( std::equal( indexes, indexes + num_nodes, entity_faces.conn[k] ) )
     552                 :            :                 {
     553         [ +  + ]:        176 :                     if( conn[k + offset] != 0 ) return conn[k + offset];
     554                 :        121 :                     k = entity_faces.num_sub_elements;
     555                 :            :                 }
     556                 :            :                 else
     557                 :            :                 {
     558                 :        357 :                     int temp               = indexes[1];
     559                 :        357 :                     indexes[1]             = indexes[num_nodes - 1];
     560                 :        357 :                     indexes[num_nodes - 1] = temp;
     561 [ +  - ][ +  + ]:        357 :                     if( std::equal( indexes, indexes + num_nodes, entity_faces.conn[k] ) )
     562                 :            :                     {
     563         [ +  + ]:        120 :                         if( conn[k + offset] != 0 ) return conn[k + offset];
     564                 :         93 :                         k = entity_faces.num_sub_elements;
     565                 :            :                     }
     566                 :            :                 }
     567                 :            :             }
     568         [ +  - ]:        214 :             ++iter;
     569                 :            :         }
     570                 :            :         else
     571                 :            :         {
     572         [ +  - ]:         68 :             iter = adj_entities.erase( iter );
     573                 :            :         }
     574                 :            :     }
     575                 :            : 
     576         [ +  + ]:       1520 :     return 0;
           [ #  #  #  # ]
     577                 :            : }
     578                 :            : 
     579                 :          0 : bool HigherOrderFactory::add_center_node( EntityType this_type, EntityHandle* element_conn, int conn_size,
     580                 :            :                                           EntityHandle corner_node1, EntityHandle corner_node2,
     581                 :            :                                           EntityHandle center_node )
     582                 :            : {
     583                 :          0 :     int first_node  = std::find( element_conn, element_conn + conn_size, corner_node1 ) - element_conn;
     584                 :          0 :     int second_node = std::find( element_conn, element_conn + conn_size, corner_node2 ) - element_conn;
     585 [ #  # ][ #  # ]:          0 :     if( first_node == conn_size || second_node == conn_size )
     586                 :          0 :         assert( "We should always find our nodes no matter what" == NULL );
     587                 :          0 :     int high_node_index           = mNodeMap[this_type][first_node][second_node];
     588                 :          0 :     element_conn[high_node_index] = center_node;
     589                 :          0 :     return true;
     590                 :            : }
     591                 :            : 
     592                 :         13 : ErrorCode HigherOrderFactory::copy_corner_nodes( ElementSequence* src, ElementSequence* dst )
     593                 :            : {
     594                 :         13 :     unsigned num_corners = CN::VerticesPerEntity( src->type() );
     595                 :         13 :     return copy_nodes( src, dst, num_corners, 0, 0 );
     596                 :            : }
     597                 :            : 
     598                 :          0 : ErrorCode HigherOrderFactory::copy_mid_edge_nodes( ElementSequence* src, ElementSequence* dst )
     599                 :            : {
     600 [ #  # ][ #  # ]:          0 :     if( !src->has_mid_edge_nodes() || !dst->has_mid_edge_nodes() ) return MB_FAILURE;
                 [ #  # ]
     601                 :            : 
     602                 :          0 :     unsigned num_corners = CN::VerticesPerEntity( src->type() );
     603         [ #  # ]:          0 :     unsigned num_edges   = ( src->type() == MBEDGE ) ? 1 : CN::NumSubEntities( src->type(), 1 );
     604                 :          0 :     return copy_nodes( src, dst, num_edges, num_corners, num_corners );
     605                 :            : }
     606                 :            : 
     607                 :          8 : ErrorCode HigherOrderFactory::zero_mid_edge_nodes( ElementSequence* dst )
     608                 :            : {
     609         [ -  + ]:          8 :     if( !dst->has_mid_edge_nodes() ) return MB_FAILURE;
     610                 :            : 
     611                 :          8 :     unsigned num_corners = CN::VerticesPerEntity( dst->type() );
     612         [ +  - ]:          8 :     unsigned num_edges   = ( dst->type() == MBEDGE ) ? 1 : CN::NumSubEntities( dst->type(), 1 );
     613                 :          8 :     return zero_nodes( dst, num_edges, num_corners );
     614                 :            : }
     615                 :            : 
     616                 :          0 : ErrorCode HigherOrderFactory::copy_mid_face_nodes( ElementSequence* src, ElementSequence* dst )
     617                 :            : {
     618 [ #  # ][ #  # ]:          0 :     if( !src->has_mid_face_nodes() || !dst->has_mid_face_nodes() ) return MB_FAILURE;
                 [ #  # ]
     619                 :            : 
     620                 :          0 :     unsigned src_offset = CN::VerticesPerEntity( src->type() );
     621                 :          0 :     unsigned dst_offset = src_offset;
     622         [ #  # ]:          0 :     if( src->has_mid_edge_nodes() ) src_offset += CN::NumSubEntities( src->type(), 1 );
     623         [ #  # ]:          0 :     if( dst->has_mid_edge_nodes() ) dst_offset += CN::NumSubEntities( dst->type(), 1 );
     624         [ #  # ]:          0 :     unsigned num_faces = ( CN::Dimension( src->type() ) == 2 ) ? 1 : CN::NumSubEntities( src->type(), 2 );
     625                 :          0 :     return copy_nodes( src, dst, num_faces, src_offset, dst_offset );
     626                 :            : }
     627                 :            : 
     628                 :          6 : ErrorCode HigherOrderFactory::zero_mid_face_nodes( ElementSequence* dst )
     629                 :            : {
     630         [ -  + ]:          6 :     if( !dst->has_mid_face_nodes() ) return MB_FAILURE;
     631                 :            : 
     632                 :          6 :     unsigned dst_offset = CN::VerticesPerEntity( dst->type() );
     633         [ +  + ]:          6 :     if( dst->has_mid_edge_nodes() ) dst_offset += CN::NumSubEntities( dst->type(), 1 );
     634         [ +  + ]:          6 :     unsigned num_faces = ( CN::Dimension( dst->type() ) == 2 ) ? 1 : CN::NumSubEntities( dst->type(), 2 );
     635                 :          6 :     return zero_nodes( dst, num_faces, dst_offset );
     636                 :            : }
     637                 :            : 
     638                 :          0 : ErrorCode HigherOrderFactory::copy_mid_volume_nodes( ElementSequence* src, ElementSequence* dst )
     639                 :            : {
     640 [ #  # ][ #  # ]:          0 :     if( !src->has_mid_volume_nodes() || !dst->has_mid_volume_nodes() ) return MB_FAILURE;
                 [ #  # ]
     641                 :            : 
     642                 :          0 :     unsigned src_offset = CN::VerticesPerEntity( src->type() );
     643                 :          0 :     unsigned dst_offset = src_offset;
     644         [ #  # ]:          0 :     if( src->has_mid_edge_nodes() ) src_offset += CN::NumSubEntities( src->type(), 1 );
     645         [ #  # ]:          0 :     if( dst->has_mid_edge_nodes() ) dst_offset += CN::NumSubEntities( dst->type(), 1 );
     646         [ #  # ]:          0 :     if( src->has_mid_face_nodes() ) src_offset += CN::NumSubEntities( src->type(), 2 );
     647         [ #  # ]:          0 :     if( dst->has_mid_face_nodes() ) dst_offset += CN::NumSubEntities( dst->type(), 2 );
     648                 :          0 :     return copy_nodes( src, dst, 1, src_offset, dst_offset );
     649                 :            : }
     650                 :            : 
     651                 :          4 : ErrorCode HigherOrderFactory::zero_mid_volume_nodes( ElementSequence* dst )
     652                 :            : {
     653         [ -  + ]:          4 :     if( !dst->has_mid_volume_nodes() ) return MB_FAILURE;
     654                 :            : 
     655                 :          4 :     unsigned dst_offset = CN::VerticesPerEntity( dst->type() );
     656         [ +  + ]:          4 :     if( dst->has_mid_edge_nodes() ) dst_offset += CN::NumSubEntities( dst->type(), 1 );
     657         [ +  + ]:          4 :     if( dst->has_mid_face_nodes() ) dst_offset += CN::NumSubEntities( dst->type(), 2 );
     658                 :          4 :     return zero_nodes( dst, 1, dst_offset );
     659                 :            : }
     660                 :            : 
     661                 :         13 : ErrorCode HigherOrderFactory::copy_nodes( ElementSequence* src, ElementSequence* dst, unsigned nodes_per_elem,
     662                 :            :                                           unsigned src_offset, unsigned dst_offset )
     663                 :            : {
     664         [ -  + ]:         13 :     if( src->type() != dst->type() ) return MB_FAILURE;
     665                 :            : 
     666                 :         13 :     unsigned src_stride    = src->nodes_per_element();
     667                 :         13 :     unsigned dst_stride    = dst->nodes_per_element();
     668                 :         13 :     EntityHandle* src_conn = src->get_connectivity_array();
     669                 :         13 :     EntityHandle* dst_conn = dst->get_connectivity_array();
     670 [ +  - ][ -  + ]:         13 :     if( !src_conn || !dst_conn ) return MB_FAILURE;
     671                 :            : 
     672 [ +  - ][ -  + ]:         13 :     if( dst->start_handle() < src->start_handle() || dst->end_handle() > src->end_handle() ) return MB_FAILURE;
                 [ -  + ]
     673                 :            : 
     674                 :         13 :     src_conn += ( dst->start_handle() - src->start_handle() ) * src_stride;
     675                 :         13 :     EntityID count = dst->size();
     676         [ +  + ]:        175 :     for( EntityID i = 0; i < count; ++i )
     677                 :            :     {
     678         [ +  + ]:       1034 :         for( unsigned j = 0; j < nodes_per_elem; ++j )
     679                 :        872 :             dst_conn[j + dst_offset] = src_conn[j + src_offset];
     680                 :        162 :         src_conn += src_stride;
     681                 :        162 :         dst_conn += dst_stride;
     682                 :            :     }
     683                 :            : 
     684                 :         13 :     return MB_SUCCESS;
     685                 :            : }
     686                 :            : 
     687                 :         18 : ErrorCode HigherOrderFactory::zero_nodes( ElementSequence* dst, unsigned nodes_per_elem, unsigned offset )
     688                 :            : {
     689                 :         18 :     unsigned dst_stride    = dst->nodes_per_element();
     690                 :         18 :     EntityHandle* dst_conn = dst->get_connectivity_array();
     691         [ -  + ]:         18 :     if( !dst_conn ) return MB_FAILURE;
     692                 :            : 
     693                 :         18 :     EntityID count = dst->size();
     694         [ +  + ]:        250 :     for( EntityID i = 0; i < count; ++i )
     695                 :            :     {
     696         [ +  - ]:        232 :         std::fill( dst_conn + offset, dst_conn + offset + nodes_per_elem, 0 );
     697                 :        232 :         dst_conn += dst_stride;
     698                 :            :     }
     699                 :            : 
     700                 :         18 :     return MB_SUCCESS;
     701                 :            : }
     702                 :            : 
     703                 :          2 : ErrorCode HigherOrderFactory::remove_mid_edge_nodes( ElementSequence* seq, EntityHandle start, EntityHandle end,
     704                 :            :                                                      Tag deletable_nodes )
     705                 :            : {
     706                 :            :     int count;
     707                 :            :     int offset;
     708         [ -  + ]:          2 :     if( seq->type() == MBEDGE )
     709                 :            :     {
     710                 :          0 :         count  = 1;
     711                 :          0 :         offset = 2;
     712                 :            :     }
     713                 :            :     else
     714                 :            :     {
     715                 :          2 :         count  = CN::NumSubEntities( seq->type(), 1 );
     716                 :          2 :         offset = CN::VerticesPerEntity( seq->type() );
     717                 :            :     }
     718                 :            : 
     719                 :          2 :     return remove_ho_nodes( seq, start, end, count, offset, deletable_nodes );
     720                 :            : }
     721                 :            : 
     722                 :          0 : ErrorCode HigherOrderFactory::remove_mid_face_nodes( ElementSequence* seq, EntityHandle start, EntityHandle end,
     723                 :            :                                                      Tag deletable_nodes )
     724                 :            : {
     725                 :            :     int count;
     726         [ #  # ]:          0 :     if( CN::Dimension( seq->type() ) == 2 )
     727                 :          0 :         count = 1;
     728                 :            :     else
     729                 :          0 :         count = CN::NumSubEntities( seq->type(), 2 );
     730                 :          0 :     int offset = CN::VerticesPerEntity( seq->type() );
     731         [ #  # ]:          0 :     if( seq->has_mid_edge_nodes() ) offset += CN::NumSubEntities( seq->type(), 1 );
     732                 :            : 
     733                 :          0 :     return remove_ho_nodes( seq, start, end, count, offset, deletable_nodes );
     734                 :            : }
     735                 :            : 
     736                 :          0 : ErrorCode HigherOrderFactory::remove_mid_volume_nodes( ElementSequence* seq, EntityHandle start, EntityHandle end,
     737                 :            :                                                        Tag deletable_nodes )
     738                 :            : {
     739                 :          0 :     int offset = CN::VerticesPerEntity( seq->type() );
     740         [ #  # ]:          0 :     if( seq->has_mid_edge_nodes() ) offset += CN::NumSubEntities( seq->type(), 1 );
     741         [ #  # ]:          0 :     if( seq->has_mid_face_nodes() ) offset += CN::NumSubEntities( seq->type(), 2 );
     742                 :            : 
     743                 :          0 :     return remove_ho_nodes( seq, start, end, 1, offset, deletable_nodes );
     744                 :            : }
     745                 :            : 
     746                 :            : // Code mostly copied from old EntitySequence.cpp
     747                 :            : // (ElementEntitySequence::convert_realloc &
     748                 :            : //  ElementEntitySequence::tag_for_deletion).
     749                 :            : // Copyright from old EntitySequence.cpp:
     750                 :            : /**
     751                 :            :  * MOAB, a Mesh-Oriented datABase, is a software component for creating,
     752                 :            :  * storing and accessing finite element mesh data.
     753                 :            :  *
     754                 :            :  * Copyright 2004 Sandia Corporation.  Under the terms of Contract
     755                 :            :  * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government
     756                 :            :  * retains certain rights in this software.
     757                 :            :  *
     758                 :            :  * This library is free software; you can redistribute it and/or
     759                 :            :  * modify it under the terms of the GNU Lesser General Public
     760                 :            :  * License as published by the Free Software Foundation; either
     761                 :            :  * version 2.1 of the License, or (at your option) any later version.
     762                 :            :  *
     763                 :            :  */
     764                 :          2 : ErrorCode HigherOrderFactory::remove_ho_nodes( ElementSequence* seq, EntityHandle start, EntityHandle end,
     765                 :            :                                                int nodes_per_elem, int elem_conn_offset, Tag deletable_nodes )
     766                 :            : {
     767 [ +  - ][ +  - ]:          2 :     if( start < seq->start_handle() || end > seq->end_handle() ) return MB_ENTITY_NOT_FOUND;
         [ +  - ][ -  + ]
                 [ -  + ]
     768         [ +  - ]:          2 :     EntityHandle* array = seq->get_connectivity_array();
     769         [ -  + ]:          2 :     if( !array ) return MB_NOT_IMPLEMENTED;
     770                 :            : 
     771         [ +  - ]:          2 :     std::set< EntityHandle > nodes_processed;
     772         [ +  + ]:         18 :     for( EntityHandle i = start; i <= end; ++i )
     773                 :            :     {  // for each element
     774         [ +  + ]:        208 :         for( int j = 0; j < nodes_per_elem; ++j )
     775                 :            :         {                                                        // for each HO node to remove
     776         [ +  - ]:        192 :             const EntityID elem  = ( i - seq->start_handle() );  // element index
     777                 :        192 :             const int conn_idx   = j + elem_conn_offset;
     778         [ +  - ]:        192 :             const EntityID index = elem * seq->nodes_per_element() + conn_idx;
     779 [ +  - ][ +  - ]:        192 :             if( array[index] && nodes_processed.insert( array[index] ).second )
         [ +  + ][ +  + ]
     780                 :            :             {
     781 [ +  - ][ +  - ]:        177 :                 if( tag_for_deletion( i, conn_idx, seq ) )
     782                 :            :                 {
     783                 :        177 :                     unsigned char bit = 0x1;
     784         [ +  - ]:        177 :                     mMB->tag_set_data( deletable_nodes, &( array[index] ), 1, &bit );
     785                 :            :                 }
     786                 :            :             }
     787                 :            :         }
     788                 :            :     }
     789                 :            : 
     790                 :          2 :     return MB_SUCCESS;
     791                 :            : }
     792                 :            : 
     793                 :        177 : bool HigherOrderFactory::tag_for_deletion( EntityHandle parent_handle, int conn_index, ElementSequence* seq )
     794                 :            : {
     795                 :            :     // get type of this sequence
     796         [ +  - ]:        177 :     EntityType this_type = seq->type();
     797                 :            : 
     798                 :            :     // get dimension of 'parent' element
     799         [ +  - ]:        177 :     int this_dimension = mMB->dimension_from_handle( parent_handle );
     800                 :            : 
     801                 :            :     // tells us if higher order node is on
     802                 :            :     int dimension, side_number;
     803 [ +  - ][ +  - ]:        177 :     CN::HONodeParent( this_type, seq->nodes_per_element(), conn_index, dimension, side_number );
     804                 :            : 
     805                 :            :     // it MUST be a higher-order node
     806                 :        177 :     bool delete_node = false;
     807                 :            : 
     808         [ -  + ]:        177 :     assert( dimension != -1 );
     809         [ -  + ]:        177 :     assert( side_number != -1 );
     810                 :            : 
     811                 :            :     // could be a mid-volume/face/edge node on a hex/face/edge respectively
     812                 :            :     // if so...delete it bc/ no one else owns it too
     813         [ +  - ]:        177 :     std::vector< EntityHandle > connectivity;
     814 [ -  + ][ #  # ]:        177 :     if( dimension == this_dimension && side_number == 0 )
     815                 :          0 :         delete_node = true;
     816                 :            :     else  // the node could also be on a lower order entity of 'tmp_entity'
     817                 :            :     {
     818                 :            :         // get 'side' of 'parent_handle' that node is on
     819                 :        177 :         EntityHandle target_entity = 0;
     820         [ +  - ]:        177 :         mMB->side_element( parent_handle, dimension, side_number, target_entity );
     821                 :            : 
     822         [ -  + ]:        177 :         if( target_entity )
     823                 :            :         {
     824         [ #  # ]:          0 :             AEntityFactory* a_fact = mMB->a_entity_factory();
     825                 :            :             EntityHandle low_meshset;
     826                 :            :             int dum;
     827         [ #  # ]:          0 :             low_meshset = CREATE_HANDLE( MBENTITYSET, 0, dum );
     828                 :            : 
     829                 :            :             // just get corner nodes of target_entity
     830                 :          0 :             connectivity.clear();
     831                 :            :             ErrorCode rval;
     832 [ #  # ][ #  # ]:          0 :             rval = mMB->get_connectivity( &( target_entity ), 1, connectivity, true );MB_CHK_ERR( rval );
         [ #  # ][ #  # ]
     833                 :            : 
     834                 :            :             // for each node, get all common adjacencies of nodes in 'parent_handle'
     835 [ #  # ][ #  # ]:          0 :             std::vector< EntityHandle > adj_list_1, adj_list_2, adj_entities;
                 [ #  # ]
     836 [ #  # ][ #  # ]:          0 :             a_fact->get_adjacencies( connectivity[0], adj_list_1 );
     837                 :            : 
     838                 :            :             // remove meshsets
     839                 :            :             adj_list_1.erase(
     840                 :            :                 std::remove_if( adj_list_1.begin(), adj_list_1.end(),
     841                 :            :                                 std::bind( std::greater< EntityHandle >(), std::placeholders::_1, low_meshset ) ),
     842 [ #  # ][ #  # ]:          0 :                 adj_list_1.end() );
                 [ #  # ]
     843                 :            :             // std::bind2nd(std::greater<EntityHandle>(),low_meshset)), adj_list_1.end());
     844                 :            :             // https://stackoverflow.com/questions/32739018/a-replacement-for-stdbind2nd
     845                 :            : 
     846                 :            :             size_t i;
     847         [ #  # ]:          0 :             for( i = 1; i < connectivity.size(); i++ )
     848                 :            :             {
     849                 :          0 :                 adj_list_2.clear();
     850 [ #  # ][ #  # ]:          0 :                 a_fact->get_adjacencies( connectivity[i], adj_list_2 );
     851                 :            : 
     852                 :            :                 // remove meshsets
     853                 :            :                 adj_list_2.erase(
     854                 :            :                     std::remove_if( adj_list_2.begin(), adj_list_2.end(),
     855                 :            :                                     std::bind( std::greater< EntityHandle >(), std::placeholders::_1, low_meshset ) ),
     856 [ #  # ][ #  # ]:          0 :                     adj_list_2.end() );
                 [ #  # ]
     857                 :            :                 // std::bind2nd(std::greater<EntityHandle>(),low_meshset)), adj_list_2.end());
     858                 :            :                 // https://stackoverflow.com/questions/32739018/a-replacement-for-stdbind2nd
     859                 :            : 
     860                 :            :                 // intersect the 2 lists
     861                 :          0 :                 adj_entities.clear();
     862                 :            :                 std::set_intersection( adj_list_1.begin(), adj_list_1.end(), adj_list_2.begin(), adj_list_2.end(),
     863 [ #  # ][ #  # ]:          0 :                                        std::back_inserter< std::vector< EntityHandle > >( adj_entities ) );
     864                 :          0 :                 adj_list_1.clear();
     865         [ #  # ]:          0 :                 adj_list_1 = adj_entities;
     866                 :            :             }
     867                 :            : 
     868         [ #  # ]:          0 :             assert( adj_entities.size() );  // has to have at least one adjacency
     869                 :            : 
     870                 :            :             // see if node is in other elements, not in this sequence...if so, delete it
     871         [ #  # ]:          0 :             for( i = 0; i < adj_entities.size(); i++ )
     872                 :            :             {
     873 [ #  # ][ #  # ]:          0 :                 if( adj_entities[i] >= seq->start_handle() && adj_entities[i] <= seq->end_handle() )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     874                 :            :                 {
     875                 :          0 :                     delete_node = false;
     876                 :          0 :                     break;
     877                 :            :                 }
     878                 :            :                 else
     879                 :          0 :                     delete_node = true;
     880                 :          0 :             }
     881                 :            :         }
     882                 :            :         else  // there is no lower order entity that also contains node
     883                 :        177 :             delete_node = true;
     884                 :            :     }
     885                 :            : 
     886                 :        177 :     return delete_node;
     887                 :            : }
     888                 :            : 
     889 [ +  - ][ +  - ]:        228 : }  // namespace moab

Generated by: LCOV version 1.11