Mesh Oriented datABase
(version 5.4.1)
Array-based unstructured mesh datastructure
|
00001 /* 00002 * MOAB, a Mesh-Oriented datABase, is a software component for creating, 00003 * storing and accessing finite element mesh data. 00004 * 00005 * Copyright 2004 Sandia Corporation. Under the terms of Contract 00006 * DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government 00007 * retains certain rights in this software. 00008 * 00009 * This library is free software; you can redistribute it and/or 00010 * modify it under the terms of the GNU Lesser General Public 00011 * License as published by the Free Software Foundation; either 00012 * version 2.1 of the License, or (at your option) any later version. 00013 * 00014 */ 00015 00016 /**\file RangeSeqIntersectIter.cpp 00017 *\author Jason Kraftcheck ([email protected]) 00018 *\date 2006-08-11 00019 */ 00020 00021 #include "RangeSeqIntersectIter.hpp" 00022 #include "SequenceManager.hpp" 00023 #include "EntitySequence.hpp" 00024 #include <cassert> 00025 00026 namespace moab 00027 { 00028 00029 ErrorCode RangeSeqIntersectIter::init( Range::const_iterator start, Range::const_iterator end ) 00030 { 00031 mSequence = 0; 00032 rangeIter = start; 00033 00034 // special case : nothing to iterate over 00035 if( start == end ) 00036 { 00037 mStartHandle = mEndHandle = mLastHandle = 0; 00038 return MB_FAILURE; 00039 } 00040 00041 // normal case 00042 mStartHandle = *start; 00043 --end; 00044 mLastHandle = *end; 00045 mEndHandle = ( *rangeIter ).second; 00046 if( mEndHandle > mLastHandle ) mEndHandle = mLastHandle; 00047 00048 #if MB_RANGE_SEQ_INTERSECT_ITER_STATS 00049 ErrorCode result = update_entity_sequence(); 00050 update_stats( mEndHandle - mStartHandle + 1 ); 00051 return result; 00052 #else 00053 return update_entity_sequence(); 00054 #endif 00055 } 00056 00057 ErrorCode RangeSeqIntersectIter::step() 00058 { 00059 // If at end, return MB_FAILURE 00060 if( is_at_end() ) return MB_FAILURE; 00061 // If the last block was at the end of the rangeIter pair, 00062 // then advance the iterator and set the next block 00063 else if( mEndHandle == ( *rangeIter ).second ) 00064 { 00065 ++rangeIter; 00066 mStartHandle = ( *rangeIter ).first; 00067 } 00068 // Otherwise start with next entity in the pair 00069 else 00070 { 00071 mStartHandle = mEndHandle + 1; 00072 } 00073 // Always take the remaining entities in the rangeIter pair. 00074 // will trim up the end of the range in update_entity_sequence(). 00075 mEndHandle = ( *rangeIter ).second; 00076 if( mEndHandle > mLastHandle ) mEndHandle = mLastHandle; 00077 00078 // Now trim up the range (decrease mEndHandle) as necessary 00079 // for the corresponding EntitySquence 00080 #if MB_RANGE_SEQ_INTERSECT_ITER_STATS 00081 ErrorCode result = update_entity_sequence(); 00082 update_stats( mEndHandle - mStartHandle + 1 ); 00083 return result; 00084 #else 00085 return update_entity_sequence(); 00086 #endif 00087 } 00088 00089 ErrorCode RangeSeqIntersectIter::update_entity_sequence() 00090 { 00091 // mStartHandle to mEndHandle is a subset of the Range. 00092 // Update sequence data as necessary and trim that subset 00093 // (reduce mEndHandle) for the current EntitySequence. 00094 00095 // Need to update the sequence pointer? 00096 if( !mSequence || mStartHandle > mSequence->end_handle() ) 00097 { 00098 00099 // Check that the mStartHandle is valid 00100 if( TYPE_FROM_HANDLE( mStartHandle ) >= MBMAXTYPE ) return MB_TYPE_OUT_OF_RANGE; 00101 00102 if( MB_SUCCESS != mSequenceManager->find( mStartHandle, mSequence ) ) return find_invalid_range(); 00103 } 00104 00105 // if mEndHandle is past end of sequence or block of used 00106 // handles within sequence, shorten it. 00107 if( mEndHandle > mSequence->end_handle() ) mEndHandle = mSequence->end_handle(); 00108 00109 return MB_SUCCESS; 00110 } 00111 00112 ErrorCode RangeSeqIntersectIter::find_invalid_range() 00113 { 00114 assert( !mSequence ); 00115 00116 // no more entities in current range 00117 if( mStartHandle == mEndHandle ) return MB_ENTITY_NOT_FOUND; 00118 00119 // Find the next EntitySequence 00120 EntityType type = TYPE_FROM_HANDLE( mStartHandle ); 00121 const TypeSequenceManager& map = mSequenceManager->entity_map( type ); 00122 TypeSequenceManager::const_iterator iter = map.upper_bound( mStartHandle ); 00123 // If no next sequence of the same type 00124 if( iter == map.end() ) 00125 { 00126 // If end type not the same as start type, split on type 00127 if( type != TYPE_FROM_HANDLE( mEndHandle ) ) 00128 { 00129 int junk; 00130 mEndHandle = CREATE_HANDLE( type, MB_END_ID, junk ); 00131 } 00132 } 00133 // otherwise invalid range ends at min(mEndHandle, sequence start handle - 1) 00134 else if( ( *iter )->start_handle() <= mEndHandle ) 00135 { 00136 mEndHandle = ( *iter )->start_handle() - 1; 00137 } 00138 00139 return MB_ENTITY_NOT_FOUND; 00140 } 00141 00142 #if MB_RANGE_SEQ_INTERSECT_ITER_STATS 00143 double RangeSeqIntersectIter::doubleNumCalls = 0; 00144 double RangeSeqIntersectIter::doubleEntCount = 0; 00145 unsigned long RangeSeqIntersectIter::intNumCalls = 0; 00146 unsigned long RangeSeqIntersectIter::intEntCount = 0; 00147 00148 void RangeSeqIntersectIter::update_stats( unsigned long num_ents ) 00149 { 00150 if( std::numeric_limits< unsigned long >::max() == intNumCalls ) 00151 { 00152 doubleNumCalls += intNumCalls; 00153 intNumCalls = 0; 00154 } 00155 ++intNumCalls; 00156 00157 if( std::numeric_limits< unsigned long >::max() - intEntCount > num_ents ) 00158 { 00159 doubleNumCalls += intEntCount; 00160 intEntCount = num_ents; 00161 } 00162 else 00163 { 00164 intEntCount += num_ents; 00165 } 00166 } 00167 #endif 00168 00169 } // namespace moab