Sierra Toolkit Version of the Day
FindRestriction.hpp
00001 /*------------------------------------------------------------------------*/
00002 /*                 Copyright 2010 Sandia Corporation.                     */
00003 /*  Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive   */
00004 /*  license for use of this work by or on behalf of the U.S. Government.  */
00005 /*  Export of this program may require a license from the                 */
00006 /*  United States Government.                                             */
00007 /*------------------------------------------------------------------------*/
00008 
00009 
00010 #ifndef stk_mesh_base_FindRestriction_hpp
00011 #define stk_mesh_base_FindRestriction_hpp
00012 
00013 #include <stk_mesh/base/Types.hpp>
00014 #include <stk_mesh/base/FieldBase.hpp>
00015 #include <stk_mesh/base/FieldRestriction.hpp>
00016 #include <stk_mesh/base/Selector.hpp>
00017 
00018 namespace stk {
00019 namespace mesh {
00020 
00021 namespace {
00022 inline
00023 const FieldBase::Restriction & empty_field_restriction()
00024 {
00025   //NOT THREAD SAFE
00026   static const FieldBase::Restriction empty ;
00027   return empty ;
00028 }
00029 }//namespace anonymous
00030 
00031 //Given a field and a range of parts, determine whether the field has a restriction
00032 //for the part range. (Common usage is to provide the part-range from a bucket; i.e.,
00033 //determine whether the field should be allocated in the bucket.)
00034 template<typename PartIterator, class Compare>
00035 const FieldBase::Restriction& find_restriction(const FieldBase& field,
00036                                                EntityRank erank,
00037                                                PartIterator pbegin,
00038                                                PartIterator pend,
00039                                                Compare comp)
00040 {
00041   GetPartIterOrdinal<PartIterator> get_part_ordinal;
00042 
00043   const FieldBase::Restriction & empty = empty_field_restriction();
00044   const FieldBase::Restriction * restriction = & empty ;
00045 
00046   const std::vector<FieldBase::Restriction> & restr_vec = field.restrictions();
00047   const std::vector<FieldBase::Restriction>::const_iterator iend = restr_vec.end();
00048         std::vector<FieldBase::Restriction>::const_iterator ibeg = restr_vec.begin();
00049 
00050   //NOT THREAD SAFE
00051   static FieldRestriction restr;
00052 
00053   for ( PartIterator it = pbegin; it != pend && iend != ibeg ; ++it ) {
00054 
00055     restr.set_entity_rank(erank);
00056     restr.set_part_ordinal(get_part_ordinal(it));
00057 
00058     //lower_bound returns an iterator to either the insertion point for the
00059     //'restr' argument, or to a matching restriction.
00060     //It only returns the 'end' iterator if 'restr' is past the end of the
00061     //vector of restrictions being searched.
00062     //This depends on the input part ordinals being sorted, and on the restriction
00063     //vector being sorted by part ordinal.
00064 
00065     ibeg = std::lower_bound( ibeg , iend , restr );
00066 
00067     if ( (iend != ibeg) && (*ibeg == restr) ) {
00068       if ( restriction == & empty ) { restriction = & *ibeg ; }
00069 
00070       if ( ibeg->not_equal_stride(*restriction) ) {
00071 
00072         Part & p_old = MetaData::get(field).get_part( ibeg->part_ordinal() );
00073         Part & p_new = MetaData::get(field).get_part( restriction->part_ordinal() );
00074 
00075         std::ostringstream msg ;
00076         msg << " FAILED WITH INCOMPATIBLE DIMENSIONS FOR " ;
00077         msg << field ;
00078         msg << " Part[" << p_old.name() ;
00079         msg << "] and Part[" << p_new.name() ;
00080         msg << "]" ;
00081 
00082         ThrowErrorMsg( msg.str() );
00083       }
00084     }
00085   }
00086 
00087   const std::vector<FieldBase::Restriction> & sel_res = field.selector_restrictions();
00088   std::pair<PartIterator,PartIterator> part_range = std::make_pair(pbegin, pend);
00089   for(std::vector<FieldBase::Restriction>::const_iterator it=sel_res.begin(), it_end=sel_res.end(); it != it_end; ++it) {
00090     const Selector& selector = it->selector();
00091     if (it->entity_rank() == erank && selector.apply(part_range, comp)) {
00092       if (restriction == &empty) {
00093         restriction = &*it;
00094       }
00095       if (it->not_equal_stride(*restriction)) {
00096         ThrowErrorMsg("find_restriction calculation failed with different field-restriction selectors giving incompatible sizes.");
00097       }
00098     }
00099   }
00100 
00101   return *restriction ;
00102 }
00103 
00104 } // namespace mesh
00105 } // namespace stk
00106 
00107 #endif // stk_mesh_base_FindRestriction_hpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines