![]() |
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 (kraftche@cae.wisc.edu)
00018 *\date 2006-08-11
00019 */
00020
00021 #include "RangeSeqIntersectIter.hpp"
00022 #include "SequenceManager.hpp"
00023 #include "EntitySequence.hpp"
00024 #include
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