moab-dev
Threads by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
November 2009
- 10 participants
- 112 discussions
---
parallel/scdtest.cpp | 15 ++++++++-------
1 files changed, 8 insertions(+), 7 deletions(-)
diff --git a/parallel/scdtest.cpp b/parallel/scdtest.cpp
index 64ca4d8..4158ff2 100644
--- a/parallel/scdtest.cpp
+++ b/parallel/scdtest.cpp
@@ -42,6 +42,14 @@ void create_hexes_and_verts();
void resolve_and_exchange();
void error(MBErrorCode err);
+#define error(err) do { \
+ if((err) != MB_SUCCESS) { \
+ cerr << "Error: MOAB function failed\n"; \
+ assert((err) == MB_SUCCESS); \
+ } \
+ } while (0)
+
+
int main(int argc, char *argv[])
{
MPI_Init(&argc, &argv);
@@ -196,10 +204,3 @@ void resolve_and_exchange()
error(mbpc->exchange_ghost_cells(-1, 0, 1, true));
}
-void error(MBErrorCode err)
-{
- if(err != MB_SUCCESS) {
- cerr << "Error: MOAB function failed\n";
- assert(0);
- }
-}
--
1.6.5.3
2
7
Dagmc loads a file by calling MBInterface::load_file(). For several
reasons, dagmc wants to know what type of file is thus loaded, but
MBInterface does not provide an obvious way to find out.
Here is a roundabout way to test whether a file is handled by a given
reader (in this case, the native MOAB reader):
> // variables in scope: MBInterface* MBI, char* filename
> // cast MBInterface to MBCore and extract reader-writer set
> MBReaderWriterSet* rwset = (dynamic_cast<MBCore*>(MBI))-
> >reader_writer_set();
> // get the MOAB handler
> MBReaderWriterSet::iterator moab_reader = rwset->handler_by_name
> ("MOAB");
> // get the read handler for our file
> MBReaderWriterSet::iterator cfile_reader = rwset-
> >handler_from_extension( rwset->extension_from_filename( filename ),
> true, false );
>
> if( moab_reader == cfile_reader ){
> ... special code for MOAB files ...
> }
I have three questions:
1) Is the code above the best way for a MOAB client to check file
types? Is there a better way?
2) Should we wrap up this functionality into a more convenient
function? Perhaps something like
MBReaderWriterSet::handler_name_from_filename(), or even
MBInterface::detect_file_type(). (I realize the latter would be a
substantial interface change, but it does express the operation I am
looking for.) Another option would be to provide a new optional
argument to load_file, which would return a value indicating the file
type that was loaded.
3) Handler names are currently specified by strings given directly in
the code (e.g. "MOAB" in the above). A handler name is initially
passed to the MBReaderWriterSet::register_factory method; right now
all calls to this method are found within MBReaderWriterSet.cpp.
However, if we want to use these handler names to distinguish file
types outside of the implementation of MBReaderWriterSet, it might
make sense to #define the strings somewhere. Would such defines be
appropriate, and if so, where should they go?
Paul, Tim, and I discussed this earlier today, and we would value the
input of Jason and any other interested users. I'm happy to do the
necessary implementation work, if we can agree on an approach.
Happy weekend to all,
~S
4
12
Author: kraftche
Date: 2009-11-30 17:07:51 -0600 (Mon, 30 Nov 2009)
New Revision: 3390
Added:
MOAB/trunk/BitTagServer.cpp
MOAB/trunk/BitTagServer.hpp
Removed:
MOAB/trunk/MBBits.cpp
MOAB/trunk/MBBits.hpp
Modified:
MOAB/trunk/Makefile.am
MOAB/trunk/TagServer.cpp
MOAB/trunk/TagServer.hpp
Log:
Re-write bit tag handling:
o remove much indirection (reduce length of chain of pointers followed
to access a tag value)
o round requested number of bits per tag up to a power of two, so that
tag values do not span byte boundaries
o increase memory block size from 0.5kB to 4kB.
These changes reduce the type to skin a mesh by 5-10%.
Added: MOAB/trunk/BitTagServer.cpp
===================================================================
--- MOAB/trunk/BitTagServer.cpp (rev 0)
+++ MOAB/trunk/BitTagServer.cpp 2009-11-30 23:07:51 UTC (rev 3390)
@@ -0,0 +1,404 @@
+#include "BitTagServer.hpp"
+#include "MBRange.hpp"
+#include "MBInternals.hpp"
+#include <stdlib.h>
+#include <string.h>
+
+void BitPage::search( unsigned char value, int offset, int count,
+ int per_ent, MBRange& results, MBEntityHandle start ) const
+{
+ const int end = offset + count;
+ MBRange::iterator hint = results.begin();
+ while (offset != end) {
+ if (get_bits( offset, per_ent ) == value)
+ hint = results.insert( hint, start );
+ ++offset;
+ ++start;
+ }
+}
+
+BitPage::BitPage( int per_ent, unsigned char init_val )
+{
+ unsigned char mask = (1<<per_ent)-1; // 2^per_ent - 1
+ init_val &= mask;
+ switch (per_ent) {
+ default: assert(false); abort(); break; // must be power of two
+ // Note: no breaks. fall through such that all bits in init_val are set
+ case 1: init_val |= (init_val << 1);
+ case 2: init_val |= (init_val << 2);
+ case 4: init_val |= (init_val << 4);
+ case 8: ;
+ }
+ memset( byteArray, init_val, BitTag::PageSize );
+}
+
+MBErrorCode BitTagServer::reserve_tag_id( int num_bits, MBTagId tag_id )
+{
+ if (tag_id > tagList.size())
+ tagList.resize( tag_id );
+ else if (tagList[tag_id-1].in_use())
+ return MB_ALREADY_ALLOCATED;
+
+ return tagList[tag_id-1].reserve( num_bits );
+}
+
+MBErrorCode BitTagServer::release_tag_id( MBTagId tag_id )
+{
+ if (tag_id > tagList.size() && !tagList[tag_id-1].in_use())
+ return MB_TAG_NOT_FOUND;
+
+ tagList[tag_id-1].release();
+ return MB_SUCCESS;
+}
+
+void BitTagServer::reset_data()
+{
+ for (std::vector<BitTag>::iterator i = tagList.begin(); i != tagList.end(); ++i)
+ i->reset_data();
+}
+
+MBErrorCode BitTagServer::get_tags( MBEntityHandle entity,
+ std::vector<MBTag> &tags ) const
+{
+ for (size_t i = 0; i < tagList.size(); ++i)
+ if (tagList[i].in_use())
+ tags.push_back( (MBTag)(i+1) );
+ return MB_SUCCESS;
+}
+
+MBErrorCode BitTag::reserve( unsigned bits )
+{
+ if (in_use() || bits > 8)
+ return MB_FAILURE;
+
+ inUse = true;
+ requestedBitsPerEntity = bits;
+ // store smallest power of two greater than or
+ // equal to the number of bits
+ storedBitsPerEntity = 1;
+ pageShift = Ln2PageSize+1;
+ while (storedBitsPerEntity < bits) {
+ storedBitsPerEntity *= 2;
+ }
+
+ return MB_SUCCESS;
+}
+
+void BitTag::reset_data()
+{
+ for (MBEntityType t = (MBEntityType)0; t != MBMAXTYPE; ++t) {
+ for (size_t i = 0; i < pageList[t].size(); ++i)
+ delete pageList[t][i];
+ pageList[t].clear();
+ }
+}
+
+void BitTag::release()
+{
+ reset_data();
+ inUse = false;
+}
+
+MBErrorCode BitTag::get_bits( const MBEntityHandle* handles,
+ int num_handles,
+ unsigned char* data,
+ const unsigned char* default_value ) const
+{
+ MBEntityType type;
+ size_t page;
+ int offset;
+ unsigned char def = default_value ? *default_value : 0;
+ for (int i = 0; i < num_handles; ++i) {
+ unpack( handles[i], type, page, offset );
+ if (pageList[type].size() <= page || !pageList[type][page])
+ data[i] = def;
+ else
+ data[i] = pageList[type][page]->get_bits( offset, storedBitsPerEntity );
+ }
+ return MB_SUCCESS;
+}
+
+MBErrorCode BitTag::set_bits( const MBEntityHandle* handles,
+ int num_handles,
+ const unsigned char* data,
+ const unsigned char* default_value )
+{
+ MBEntityType type;
+ size_t page;
+ int offset;
+ for (int i = 0; i < num_handles; ++i) {
+ unpack( handles[i], type, page, offset );
+ if (pageList[type].size() <= page)
+ pageList[type].resize(page+1, 0);
+ if (!pageList[type][page])
+ pageList[type][page] = new BitPage( storedBitsPerEntity,
+ default_value ? *default_value : 0 );
+ pageList[type][page]->set_bits( offset, storedBitsPerEntity, data[i] );
+ }
+ return MB_SUCCESS;
+}
+
+MBErrorCode BitTag::clear_bits( const MBEntityHandle* handles,
+ int num_handles,
+ const unsigned char* default_value )
+{
+ MBEntityType type;
+ size_t page;
+ int offset;
+ const unsigned char val = default_value ? *default_value : 0;
+ for (int i = 0; i < num_handles; ++i) {
+ unpack( handles[i], type, page, offset );
+ if (pageList[type].size() > page && pageList[type][page])
+ pageList[type][page]->set_bits( offset, storedBitsPerEntity, val );
+ }
+ return MB_SUCCESS;
+}
+
+MBErrorCode BitTag::get_bits( const MBRange& handles,
+ unsigned char* data,
+ const unsigned char* default_value ) const
+{
+ MBEntityType type;
+ MBEntityID count;
+ size_t page;
+ int offset, per_page = ents_per_page();
+ unsigned char def = default_value ? *default_value : 0;
+ MBRange::const_pair_iterator i;
+ for (i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i) {
+ unpack( i->first, type, page, offset );
+ assert(TYPE_FROM_HANDLE(i->second) == type); // should be true because id of zero is never used
+ count = i->second - i->first + 1;
+ if (page >= pageList[type].size()) {
+ memset( data, def, count );
+ data += count;
+ continue;
+ }
+
+ while (count) {
+ size_t pcount = std::min( (MBEntityID)per_page, count );
+ if (pageList[type][page])
+ pageList[type][page]->get_bits( offset, pcount, storedBitsPerEntity, data );
+ else
+ memset( data, def, pcount );
+ data += pcount;
+ count -= pcount;
+ offset = 0;
+ ++page;
+ }
+ }
+ return MB_SUCCESS;
+}
+
+MBErrorCode BitTag::set_bits( const MBRange& handles,
+ const unsigned char* data,
+ const unsigned char* default_value )
+{
+ MBEntityType type;
+ MBEntityID count;
+ size_t page;
+ int offset, per_page = ents_per_page();
+ unsigned char def = default_value ? *default_value : 0;
+ MBRange::const_pair_iterator i;
+ for (i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i) {
+ unpack( i->first, type, page, offset );
+ assert(TYPE_FROM_HANDLE(i->second) == type); // should be true because id of zero is never used
+ count = i->second - i->first + 1;
+
+ while (count) {
+ if (page >= pageList[type].size())
+ pageList[type].resize( page+1, 0 );
+ if (!pageList[type][page])
+ pageList[type][page] = new BitPage( storedBitsPerEntity, def );
+
+ size_t pcount = std::min( (MBEntityID)per_page, count );
+ pageList[type][page]->set_bits( offset, pcount, storedBitsPerEntity, data );
+ data += pcount;
+ count -= pcount;
+ offset = 0;
+ ++page;
+ }
+ }
+ return MB_SUCCESS;
+}
+
+MBErrorCode BitTag::clear_bits( const MBRange& handles,
+ const unsigned char* default_value )
+{
+ MBEntityType type;
+ MBEntityID count;
+ size_t page;
+ int offset, per_page = ents_per_page();
+ unsigned char val = default_value ? *default_value : 0;
+ MBRange::const_pair_iterator i;
+ for (i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i) {
+ unpack( i->first, type, page, offset );
+ assert(TYPE_FROM_HANDLE(i->second) == type); // should be true because id of zero is never used
+ count = i->second - i->first + 1;
+
+ while (count) {
+ size_t pcount = std::min( (MBEntityID)per_page, count );
+ if (page < pageList[type].size() && pageList[type][page])
+ pageList[type][page]->set_bits( offset, pcount, storedBitsPerEntity, val );
+ count -= pcount;
+ offset = 0;
+ ++page;
+ }
+ }
+ return MB_SUCCESS;
+}
+
+MBErrorCode BitTag::get_entities( MBRange& entities ) const
+{
+ MBErrorCode rval = MB_SUCCESS;
+ MBEntityType type = MBMAXTYPE;
+ while (type--) {
+ rval = get_entities( type, entities );
+ if (MB_SUCCESS != rval)
+ break;
+ }
+ return rval;
+}
+
+
+MBErrorCode BitTag::get_entities( MBEntityType type, MBRange& entities ) const
+{
+ const int per_page = ents_per_page();
+ MBRange::iterator hint = entities.begin();
+ for (size_t i = 0; i < pageList[type].size(); ++i) {
+ if (pageList[type][i]) {
+ MBEntityID id = i * per_page;
+ MBEntityHandle h = CREATE_HANDLE( type, id );
+ MBEntityHandle last = h + per_page - 1;
+ // never zero ID
+ if (!id) ++h;
+ hint = entities.insert( h, last );
+ }
+ }
+ return MB_SUCCESS;
+}
+
+MBErrorCode BitTag::get_entities( const MBRange& range,
+ MBEntityType in_type,
+ MBRange& entities ) const
+{
+ MBEntityType type;
+ MBEntityID count;
+ size_t page;
+ int offset, per_page = ents_per_page();
+ MBRange::const_iterator j, i = range.lower_bound( in_type );
+ MBEntityHandle h;
+ while (i != range.end()) {
+ h = *i;
+ unpack( h, type, page, offset );
+ if (type != in_type)
+ break;
+
+ i = i.end_of_block();
+ count = *i - h + 1;
+ ++i;
+ while (count > 0) {
+ MBEntityID pcount = std::min( count, (MBEntityID)(per_page - offset) );
+ if (page < pageList[type].size() && pageList[type][page])
+ entities.insert( h, h+pcount-1 );
+
+ count -= pcount;
+ h += pcount;
+ assert(TYPE_FROM_HANDLE(h) == type);
+ offset = 0;
+ ++page;
+ }
+ }
+ return MB_SUCCESS;
+}
+
+MBErrorCode BitTag::get_entities_with_bits( MBEntityType type,
+ MBRange& entities,
+ unsigned char bits ) const
+{
+ const int per_page = ents_per_page();
+ for (size_t i = 0; i < pageList[type].size(); ++i) {
+ if (pageList[type][i]) {
+ MBEntityID id = i * per_page;
+ MBEntityHandle h = CREATE_HANDLE( type, id );
+ int off = !i; // never zero ID
+ pageList[type][i]->search( bits, off, per_page-off, storedBitsPerEntity,
+ entities, h+off );
+ }
+ }
+ return MB_SUCCESS;
+}
+
+MBErrorCode BitTag::get_entities_with_bits( const MBRange &range,
+ MBEntityType in_type,
+ MBRange& entities,
+ unsigned char bits ) const
+{
+ MBEntityType type;
+ MBEntityID count;
+ size_t page;
+ int offset, per_page = ents_per_page();
+ MBRange::const_iterator j, i = range.lower_bound( in_type );
+ MBEntityHandle h;
+ while (i != range.end()) {
+ h = *i;
+ unpack( h, type, page, offset );
+ if (type != in_type)
+ break;
+
+ i = i.end_of_block();
+ count = *i - h + 1;
+ ++i;
+ while (count > 0) {
+ MBEntityID pcount = std::min( count, (MBEntityID)(per_page - offset) );
+ if (page < pageList[type].size() && pageList[type][page])
+ pageList[type][page]->search( bits, offset, pcount,
+ storedBitsPerEntity,
+ entities, h );
+
+ count -= pcount;
+ h += pcount;
+ assert(TYPE_FROM_HANDLE(h) == type);
+ offset = 0;
+ ++page;
+ }
+ }
+ return MB_SUCCESS;
+}
+
+MBErrorCode BitTag::get_number_entities( MBEntityType type,
+ int& num_entities ) const
+{
+ const int per_page = ents_per_page();
+ num_entities = 0;
+ if (pageList[type].empty())
+ return MB_SUCCESS;
+ if (pageList[type][0])
+ num_entities = per_page - 1; // never zero ID
+ for (size_t i = 1; i < pageList[type].size(); ++i)
+ if (pageList[type][i])
+ num_entities += per_page;
+ return MB_SUCCESS;
+}
+
+MBErrorCode BitTag::get_number_entities( const MBRange &range,
+ MBEntityType type,
+ int& num_entities ) const
+{
+ MBRange tmp;
+ MBErrorCode result = get_entities( range, type, tmp );
+ num_entities = tmp.size();
+ return result;
+}
+
+MBErrorCode BitTag::get_memory_use( unsigned long& total,
+ unsigned long& per_entity ) const
+{
+ per_entity = (storedBitsPerEntity > 4); // cannot return fraction of bytes, so round
+ for (MBEntityType t = (MBEntityType)0; t < MBMAXTYPE; ++t) {
+ total += pageList[t].capacity() * sizeof(BitPage*);
+ for (size_t i = 0; i < pageList[t].size(); ++i)
+ if (pageList[t][i])
+ total += sizeof(BitPage);
+ }
+ return MB_SUCCESS;
+}
Added: MOAB/trunk/BitTagServer.hpp
===================================================================
--- MOAB/trunk/BitTagServer.hpp (rev 0)
+++ MOAB/trunk/BitTagServer.hpp 2009-11-30 23:07:51 UTC (rev 3390)
@@ -0,0 +1,613 @@
+#ifndef BIT_TAG_SERVER_HPP
+#define BIT_TAG_SERVER_HPP
+
+#include "MBTypes.h"
+#include "MBInternals.hpp"
+#include <algorithm>
+#include <vector>
+#include <assert.h>
+
+class MBRange;
+class BitTag;
+class BitPage;
+
+/**\brief Manage all bit tag data
+ *
+ * This class manages data for all bit tags.
+ */
+class BitTagServer
+{
+public:
+
+ /**\brief Clear all tag data
+ *
+ * Clear all tag values, but keep the actual tags
+ */
+ void reset_data();
+
+ /** Allocate space for a tag with the specified ID.
+ * Returns MB_TAG_NOT_FOUND if ID is already in use.
+ *\param num_bits Number of bits in each per-entity tag value
+ */
+ MBErrorCode reserve_tag_id( int num_bits, MBTagId tag_id );
+
+ /**\brief Deallocate tag
+ *
+ * Mask specified tag id as unused and release any memory
+ * associated with the tag.
+ */
+ MBErrorCode release_tag_id( MBTagId tag_id );
+
+ /**\brief Get tag values for an array of entity handles */
+ MBErrorCode get_bits( MBTagId tag_id,
+ const MBEntityHandle* handles,
+ int num_handles,
+ unsigned char* data,
+ const unsigned char* default_value ) const;
+ /**\brief Get tag values for a range of entity handles */
+ MBErrorCode get_bits( MBTagId tag_id,
+ const MBRange& handles,
+ unsigned char* data,
+ const unsigned char* default_value ) const;
+
+ /**\brief Set tag values for an array of entity handles */
+ MBErrorCode set_bits( MBTagId tag_id,
+ const MBEntityHandle* handles,
+ int num_handles,
+ const unsigned char* data,
+ const unsigned char* default_value );
+ /**\brief Set tag values for a range of entity handles */
+ MBErrorCode set_bits( MBTagId tag_id,
+ const MBRange& handles,
+ const unsigned char* data,
+ const unsigned char* default_value );
+
+ /**\brief Clear tag values for an array of entity handles */
+ MBErrorCode clear_bits( MBTagId tag_id,
+ const MBEntityHandle* handles,
+ int num_handles,
+ const unsigned char* default_value );
+ /**\brief Clear tag values for a range of entity handles */
+ MBErrorCode clear_bits( MBTagId tag_id,
+ const MBRange& handles,
+ const unsigned char* default_value );
+
+ /**\brief Get entities for which an explicit tag value is stored */
+ MBErrorCode get_entities( MBTagId tag_id,
+ MBRange& entities ) const;
+
+ /**\brief Get entities for which an explicit tag value is stored */
+ MBErrorCode get_entities( MBTagId tag_id,
+ MBEntityType type,
+ MBRange& entities ) const;
+
+ /**\brief Get entities for which an explicit tag of the specified value is stored */
+ MBErrorCode get_entities_with_tag_value( MBTagId tag_id,
+ MBEntityType type,
+ MBRange& entities,
+ unsigned char bits ) const;
+
+ /**\brief Get entities for which an explicit tag value is stored */
+ MBErrorCode get_entities( const MBRange &range,
+ MBTagId tag_id,
+ MBEntityType type,
+ MBRange& entities ) const;
+
+ /**\brief Get entities for which an explicit tag of the specified value is stored */
+ MBErrorCode get_entities_with_tag_value( const MBRange &range,
+ MBTagId tag_id,
+ MBEntityType type,
+ MBRange& entities,
+ unsigned char bits ) const;
+
+ //! get all tags defined on an entity
+ MBErrorCode get_tags( MBEntityHandle entity,
+ std::vector<MBTag> &tags ) const;
+
+ /**\brief Get number of entities for which an explicit tag value is stored */
+ MBErrorCode get_number_entities( MBTagId tag_id,
+ MBEntityType type,
+ int& num_entities ) const;
+
+ /**\brief Get number of entities for which an explicit tag value is stored */
+ MBErrorCode get_number_entities( const MBRange &range,
+ MBTagId tag_id,
+ MBEntityType type,
+ int& num_entities ) const;
+
+ MBErrorCode get_memory_use( MBTagId tag,
+ unsigned long& total,
+ unsigned long& per_entity ) const;
+
+private:
+
+ /**\brief Get BitTag instance for specified tag ID, or NULL if none */
+ inline BitTag* get_tag( MBTagId id );
+
+ /**\brief Get BitTag instance for specified tag ID, or NULL if none */
+ inline const BitTag* get_tag( MBTagId id ) const;
+
+ /**\brief Array of BitTag instances, indexed by (tag id - 1) */
+ std::vector<BitTag> tagList;
+
+};
+
+/**\brief All data for a single bit tag */
+class BitTag
+{
+ public:
+
+ BitTag() : inUse(false) {}
+ ~BitTag() { release(); }
+
+ // Do destructive copying (assiging moves data from
+ // source to destination, such that source is invalid)
+ // so that resizing the vector doesn't copy data
+ BitTag( const BitTag& other )
+ { const_cast<BitTag&>(other).swap(*this); }
+ BitTag& operator=( const BitTag& other )
+ { const_cast<BitTag&>(other).swap(*this); return *this; }
+
+ /**\brief Get tag values for an array of entity handles */
+ MBErrorCode get_bits( const MBEntityHandle* handles,
+ int num_handles,
+ unsigned char* data,
+ const unsigned char* default_value ) const;
+ /**\brief Get tag values for a range of entity handles */
+ MBErrorCode get_bits( const MBRange& handles,
+ unsigned char* data,
+ const unsigned char* default_value ) const;
+
+ /**\brief Set tag values for an array of entity handles */
+ MBErrorCode set_bits( const MBEntityHandle* handles,
+ int num_handles,
+ const unsigned char* data,
+ const unsigned char* default_value );
+ /**\brief Set tag values for a range of entity handles */
+ MBErrorCode set_bits( const MBRange& handles,
+ const unsigned char* data,
+ const unsigned char* default_value );
+
+ /**\brief Clear tag values for an array of entity handles */
+ MBErrorCode clear_bits( const MBEntityHandle* handles,
+ int num_handles,
+ const unsigned char* default_value );
+ /**\brief Clear tag values for a range of entity handles */
+ MBErrorCode clear_bits( const MBRange& handles,
+ const unsigned char* default_value );
+
+
+ /**\brief Get entities for which an explicit tag value is stored */
+ MBErrorCode get_entities( MBRange& entities ) const;
+
+ /**\brief Get entities for which an explicit tag value is stored */
+ MBErrorCode get_entities( MBEntityType type,
+ MBRange& entities ) const;
+
+ /**\brief Get entities for which an explicit tag value is stored */
+ MBErrorCode get_entities( const MBRange &range,
+ MBEntityType type,
+ MBRange& entities ) const;
+
+ /**\brief Get entities for which an explicit tag of the specified value is stored */
+ MBErrorCode get_entities_with_bits( MBEntityType type,
+ MBRange& entities,
+ unsigned char bits ) const;
+
+ /**\brief Get entities for which an explicit tag of the specified value is stored */
+ MBErrorCode get_entities_with_bits( const MBRange &range,
+ MBEntityType type,
+ MBRange& entities,
+ unsigned char bits ) const;
+
+ /**\brief Get number of entities for which an explicit tag value is stored */
+ MBErrorCode get_number_entities( MBEntityType type,
+ int& num_entities ) const;
+
+ /**\brief Get number of entities for which an explicit tag value is stored */
+ MBErrorCode get_number_entities( const MBRange &range,
+ MBEntityType type,
+ int& num_entities ) const;
+
+ MBErrorCode get_memory_use( unsigned long& total,
+ unsigned long& per_entity ) const;
+
+ enum { Ln2PageSize = 12, //!< Constant: log2(PageSize)
+ PageSize = (1u << Ln2PageSize) //!< Constant: Bytes per BitPage (power of 2)
+ };
+
+ /**\return false if instance is not in use, true otherwise */
+ bool in_use() const { return inUse; }
+
+ /**\brief Release all stored tag data
+ *
+ * Releases all tag data such that tag is still defined, but stores
+ * no value for any entity.
+ */
+ void reset_data();
+
+ /**\brief Delete tag.
+ *
+ * Releases all tag data such that tag is no longer defined.
+ * Equivalent to reset_data() and setting inUse to false.
+ */
+ void release();
+
+ /**\brief Mark this instance is in use.
+ *
+ * Initialize this BitTag instance such that inUse
+ * returns true.
+ *\param bits_per_entity Desired bits per entity. Note:
+ * implementation is free to allocate more than the
+ * requested number of bits for each entity
+ */
+ MBErrorCode reserve( unsigned int bits_per_entity );
+
+ /**\brief Helper function for destructive assignment */
+ void swap( BitTag& other ) {
+ std::swap( inUse, other.inUse );
+ std::swap( storedBitsPerEntity, other.storedBitsPerEntity );
+ std::swap( requestedBitsPerEntity, other.requestedBitsPerEntity );
+ for (MBEntityType t = (MBEntityType)0; t != MBMAXTYPE; ++t)
+ pageList[t].swap( other.pageList[t] );
+ }
+
+ private:
+
+ bool inUse; //!< This instance is in use (represents data for some tag)
+ std::vector<BitPage*> pageList[MBMAXTYPE]; //!< Array of BitPage instances storing actual data.
+ unsigned int requestedBitsPerEntity; //!< user-requested bits per entity
+ unsigned int storedBitsPerEntity; //!< allocated bits per entity (power of 2)
+ unsigned int pageShift; //!< Ln2PageSize + log2(storedBitsPerEntity)
+
+ /**\brief Get indices from handle
+ *
+ *\param type Output: entity type
+ *\param page Output: index into pageList[type]
+ *\param offset Output: index into pageList[type][page]
+ */
+ void unpack( MBEntityHandle h, MBEntityType& type, size_t& page, int& offset ) const
+ {
+ type = TYPE_FROM_HANDLE(h);
+ h = ID_FROM_HANDLE(h);
+ page = ((size_t)h) >> pageShift; // h / (offset*storedBitsPerEntity)
+ offset = h & ((1u<<pageShift)-1u); // h % (offset*storedBitsPerEntity)
+ }
+
+ /**\brief Get the number of tag values that are stored in each BitPage */
+ int ents_per_page() const { return 8*PageSize/storedBitsPerEntity; }
+};
+
+/**\brief bit tag data
+ *
+ * This class represents a fixed-size block of memory in which bit tag
+ * values are stored.
+ */
+class BitPage
+{
+public:
+ /**\brief Initialize memory
+ *
+ *\param bits_per_ent Number of bits in each tag value.
+ * MUST BE A POWER OF TWO.
+ *\param init_val The lower bits_per_ent bits of this byte are
+ * used to initialize each tag value.
+ */
+ BitPage( int bits_per_ent, unsigned char init_val );
+
+ /**\brief Get tag values
+ *
+ * Get 'count' tag values, beginning with the one at 'offset'.
+ *\param offset Offset into list of values, where a value of zero indicates
+ * the first tag value, a value of one indicates the second
+ * tag value, etc. NOTE: This is the value offset, not the
+ * bit offset.
+ *\param count Number of consecutive tag values to get.
+ *\param bits_per_ent Number of bits composing each tag value.
+ * NOTE: Must be a power of two.
+ *\param data Memory into which to copy tag values. Each value is copied
+ * into a separate byte, such that the lower bits of the bit
+ * contain the tag value and any unused higher bits are zero.
+ */
+ void get_bits( int offset, int count, int bits_per_ent, unsigned char* data ) const;
+
+ /**\brief Set tag values
+ *
+ * Set 'count' tag values, beginning with the one at 'offset'.
+ *\param offset Offset into list of values, where a value of zero indicates
+ * the first tag value, a value of one indicates the second
+ * tag value, etc. NOTE: This is the value offset, not the
+ * bit offset.
+ *\param count Number of consecutive tag values to set.
+ *\param bits_per_ent Number of bits composing each tag value.
+ * NOTE: Must be a power of two.
+ *\param data Memory from which to copy tag values. Each value is copied
+ * from a separate byte. The lower 'bits_per_ent' of each
+ * byte are used as the tag value. Any additional higher bits
+ * are ignored.
+ */
+ void set_bits( int offset, int count, int bits_per_ent, const unsigned char* data );
+
+ /**\brief Set several tag values to the same value.
+ *
+ * Set 'count' tag values to specified value.
+ *\param offset Offset into list of values, where a value of zero indicates
+ * the first tag value, a value of one indicates the second
+ * tag value, etc. NOTE: This is the value offset, not the
+ * bit offset.
+ *\param count Number of consecutive tag values to set.
+ *\param bits_per_ent Number of bits composing each tag value.
+ * NOTE: Must be a power of two.
+ *\param value The lower 'bits_per_ent' of this
+ * byte are used as the tag value. Any additional higher bits
+ * are ignored.
+ */
+ void set_bits( int offset, int count, int bits_per_ent, unsigned char value );
+
+ /**\brief Get tag value
+ *
+ * Get one tag value.
+ *\param offset Offset into list of values, where a value of zero indicates
+ * the first tag value, a value of one indicates the second
+ * tag value, etc. NOTE: This is the value offset, not the
+ * bit offset.
+ *\param bits_per_ent Number of bits composing each tag value.
+ * NOTE: Must be a power of two.
+ *\return A byte containing the tag value in the lower bits with
+ * any unused higher bits zeroed.
+ */
+ unsigned char get_bits( int offset, int bits_per_ent ) const;
+
+ /**\brief Set tag value
+ *
+ * Set tag value.
+ *\param offset Offset into list of values, where a value of zero indicates
+ * the first tag value, a value of one indicates the second
+ * tag value, etc. NOTE: This is the value offset, not the
+ * bit offset.
+ *\param bits_per_ent Number of bits composing each tag value.
+ * NOTE: Must be a power of two.
+ *\param value The lower 'bits_per_ent' of this
+ * byte are used as the tag value. Any additional higher bits
+ * are ignored.
+ */
+ void set_bits( int offset, int bits_per_ent, unsigned char data );
+
+ /**\brief Search stored values for specified value.
+ *
+ * Find the offsets n in the data at which the specified value occurs,
+ * and for each one insert 'start + n' into the passed MBRange.
+ *\param value The value to look for
+ *\param offset The offset at which to begin searching
+ *\param count The number of values to search
+ *\param bits_per_ent Number of bits composing each tag value.
+ *\param results Result list.
+ *\param start The handle of the entity corresponding to the
+ * tag value stored at 'offset'
+ */
+ void search( unsigned char value, int offset, int count,
+ int bits_per_ent, MBRange& results, MBEntityHandle start ) const;
+
+private:
+
+ /**\brief The actual array of bytes */
+ char byteArray[BitTag::PageSize];
+};
+
+inline unsigned char BitPage::get_bits( int offset, int per_ent ) const
+{
+ // Assume per_ent is a power of two, which should be guaranteed
+ // by higher-level code.
+ unsigned char mask = (1<<per_ent)-1; // 2^per_ent - 1
+ int byte = (offset * per_ent) >> 3; // shifting 3 is dividing by eight
+ int bit = (offset * per_ent) & 7; // masking with 7 is modulo eight
+ assert(byte < BitTag::PageSize);
+ return (byteArray[byte] >> bit) & mask;
+}
+
+inline void BitPage::set_bits( int offset, int per_ent, unsigned char bits )
+{
+ int byte = (offset * per_ent) >> 3; // shifting 3 is dividing by eight
+ int bit = (offset * per_ent) & 7; // masking with 7 is modulo eight
+ assert(byte < BitTag::PageSize);
+ // Assume per_ent is a power of two, which should be guaranteed
+ // by higher-level code.
+ unsigned char mask = ((1<<per_ent)-1) << bit;
+ byteArray[byte] = (byteArray[byte] & ~mask) | ((bits << bit) & mask);
+}
+
+inline void BitPage::get_bits( int offset, int count, int per_ent, unsigned char* data ) const
+{
+ unsigned char* end = data+count;
+ while (data != end)
+ *(data++) = get_bits( offset++, per_ent );
+}
+
+inline void BitPage::set_bits( int offset, int count, int per_ent, const unsigned char* data )
+{
+ const unsigned char* end = data+count;
+ while (data != end)
+ set_bits( offset++, per_ent, *(data++) );
+}
+
+inline void BitPage::set_bits( int offset, int count, int per_ent, unsigned char value )
+{
+ int end = offset + count;
+ while (offset < end)
+ set_bits( offset++, per_ent, value );
+}
+
+
+inline BitTag* BitTagServer::get_tag( MBTagId id )
+ { return id-1 >= tagList.size() || !tagList[id-1].in_use() ? 0 : &tagList[id-1]; }
+
+inline const BitTag* BitTagServer::get_tag( MBTagId id ) const
+ { return id-1 >= tagList.size() || !tagList[id-1].in_use() ? 0 : &tagList[id-1]; }
+
+inline MBErrorCode
+BitTagServer::get_bits( MBTagId tag_id,
+ const MBEntityHandle* handles,
+ int num_handles,
+ unsigned char* data,
+ const unsigned char* default_value ) const
+{
+ if (const BitTag* ptr = get_tag(tag_id))
+ return ptr->get_bits( handles, num_handles, data, default_value );
+ else
+ return MB_TAG_NOT_FOUND;
+}
+
+inline MBErrorCode
+BitTagServer::get_bits( MBTagId tag_id,
+ const MBRange& handles,
+ unsigned char* data,
+ const unsigned char* default_value ) const
+{
+ if (const BitTag* ptr = get_tag(tag_id))
+ return ptr->get_bits( handles, data, default_value );
+ else
+ return MB_TAG_NOT_FOUND;
+}
+
+inline MBErrorCode
+BitTagServer::set_bits( MBTagId tag_id,
+ const MBEntityHandle* handles,
+ int num_handles,
+ const unsigned char* data,
+ const unsigned char* default_value )
+{
+ if (BitTag* ptr = get_tag(tag_id))
+ return ptr->set_bits( handles, num_handles, data, default_value );
+ else
+ return MB_TAG_NOT_FOUND;
+}
+inline MBErrorCode
+BitTagServer::set_bits( MBTagId tag_id,
+ const MBRange& handles,
+ const unsigned char* data,
+ const unsigned char* default_value )
+{
+ if (BitTag* ptr = get_tag(tag_id))
+ return ptr->set_bits( handles, data, default_value );
+ else
+ return MB_TAG_NOT_FOUND;
+}
+
+inline MBErrorCode
+BitTagServer::clear_bits( MBTagId tag_id,
+ const MBEntityHandle* handles,
+ int num_handles,
+ const unsigned char* default_value )
+{
+ if (BitTag* ptr = get_tag(tag_id))
+ return ptr->clear_bits( handles, num_handles, default_value );
+ else
+ return MB_TAG_NOT_FOUND;
+}
+inline MBErrorCode
+BitTagServer::clear_bits( MBTagId tag_id,
+ const MBRange& handles,
+ const unsigned char* default_value )
+{
+ if (BitTag* ptr = get_tag(tag_id))
+ return ptr->clear_bits( handles, default_value );
+ else
+ return MB_TAG_NOT_FOUND;
+}
+
+
+inline MBErrorCode
+BitTagServer::get_entities( MBTagId tag_id, MBRange& entities ) const
+{
+ if (const BitTag* ptr = get_tag(tag_id))
+ return ptr->get_entities( entities );
+ else
+ return MB_TAG_NOT_FOUND;
+}
+
+inline MBErrorCode
+BitTagServer::get_entities( MBTagId tag_id,
+ MBEntityType type,
+ MBRange& entities ) const
+{
+ if (const BitTag* ptr = get_tag(tag_id))
+ return ptr->get_entities( type, entities );
+ else
+ return MB_TAG_NOT_FOUND;
+}
+
+inline MBErrorCode
+BitTagServer::get_entities_with_tag_value( MBTagId tag_id,
+ MBEntityType type,
+ MBRange& entities,
+ unsigned char bits ) const
+{
+ if (const BitTag* ptr = get_tag(tag_id))
+ return ptr->get_entities_with_bits( type, entities, bits );
+ else
+ return MB_TAG_NOT_FOUND;
+}
+
+inline MBErrorCode
+BitTagServer::get_entities( const MBRange &range,
+ MBTagId tag_id,
+ MBEntityType type,
+ MBRange& entities ) const
+{
+ if (const BitTag* ptr = get_tag(tag_id))
+ return ptr->get_entities( range, type, entities );
+ else
+ return MB_TAG_NOT_FOUND;
+}
+
+inline MBErrorCode
+BitTagServer::get_entities_with_tag_value( const MBRange &range,
+ MBTagId tag_id,
+ MBEntityType type,
+ MBRange& entities,
+ unsigned char bits ) const
+{
+ if (const BitTag* ptr = get_tag(tag_id))
+ return ptr->get_entities_with_bits( range, type, entities, bits );
+ else
+ return MB_TAG_NOT_FOUND;
+}
+
+inline MBErrorCode
+BitTagServer::get_number_entities( const MBTagId tag_id,
+ const MBEntityType type,
+ int& num_entities ) const
+{
+ if (const BitTag* ptr = get_tag(tag_id))
+ return ptr->get_number_entities( type, num_entities );
+ else
+ return MB_TAG_NOT_FOUND;
+}
+
+inline MBErrorCode
+BitTagServer::get_number_entities( const MBRange &range,
+ const MBTagId tag_id,
+ const MBEntityType type,
+ int& num_entities ) const
+{
+ if (const BitTag* ptr = get_tag(tag_id))
+ return ptr->get_number_entities( range, type, num_entities );
+ else
+ return MB_TAG_NOT_FOUND;
+}
+
+inline MBErrorCode
+BitTagServer::get_memory_use( MBTagId tag,
+ unsigned long& total,
+ unsigned long& per_entity ) const
+{
+ if (const BitTag* ptr = get_tag(tag)) {
+ MBErrorCode result = ptr->get_memory_use( total, per_entity );
+ total += sizeof(*this);
+ return result;
+ }
+ else
+ return MB_TAG_NOT_FOUND;
+}
+
+#endif
Deleted: MOAB/trunk/MBBits.cpp
===================================================================
--- MOAB/trunk/MBBits.cpp 2009-11-30 23:06:35 UTC (rev 3389)
+++ MOAB/trunk/MBBits.cpp 2009-11-30 23:07:51 UTC (rev 3390)
@@ -1,552 +0,0 @@
-/**
- * MOAB, a Mesh-Oriented datABase, is a software component for creating,
- * storing and accessing finite element mesh data.
- *
- * Copyright 2004 Sandia Corporation. Under the terms of Contract
- * DE-AC04-94AL85000 with Sandia Coroporation, the U.S. Government
- * retains certain rights in this software.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- */
-
-
-
-
-/* Bit tools for MB
- *
- * File : MBBits.hpp
- * Creator: Clinton Stimpson
- * Date : 10-10-2002
- */
-
-#include "MBBits.hpp"
-#include "MBRange.hpp"
-#include <algorithm>
-
-
-/*! bit masks for how many bits to mask */
-const unsigned int MBBitManipulator::masks[9] =
-{
- 0x0,
- 0x01,
- 0x03,
- 0x07,
- 0x0F,
- 0x1F,
- 0x3F,
- 0x7F,
- 0xFF
-};
-
-/*! page size of 512 bytes for storing bits */
-const int MBBitPage::mPageSize = 512;
-
-/*! returns an available tag id to use when getting and setting bits */
-MBErrorCode MBBitServer::reserve_tag_id(int num_bits, MBTagId tag_id)
-{
- for(int i=0; i<(int)MBMAXTYPE; i++)
- if (tag_id >= mBitPageGroups[i].size())
- mBitPageGroups[i].resize( tag_id + 1, 0 );
-
- for(int i=0; i<(int)MBMAXTYPE; i++)
- if (mBitPageGroups[i][tag_id-1])
- return MB_FAILURE;
-
- for(int i=0; i<(int)MBMAXTYPE; i++)
- mBitPageGroups[i][tag_id-1] = new MBBitPageGroup(num_bits);
-
- mBitPageGroupsSize = (*mBitPageGroups).size();
-
- return MB_SUCCESS;
-}
-
-
-MBErrorCode MBBitPage::get_entities_with_value( unsigned char value,
- int offset,
- int count,
- int num_bits_per_flag,
- MBEntityHandle first,
- MBRange& results ) const
-{
- if (mBitArray) {
- MBRange::iterator hint = results.begin();
- for (int i = 0; i < count; ++i)
- if (value == MBBitManipulator::get_bits( (offset+i)*num_bits_per_flag,
- num_bits_per_flag, mBitArray))
- hint = results.insert( hint, first + i );
- }
- return MB_SUCCESS;
-}
-
-void MBBitPage::alloc_array( int num_bits_per_flag,
- const unsigned char* default_value )
-{
- assert(!mBitArray);
-
- mBitArray = new unsigned char[mPageSize];
- // Modifed by J.Kraftcheck : 31 Jan, 2008:
- // Need to initialize to default value to ensure that we return
- // the default value for unset entities.
-
- // Zero memory if no default value. Also, if default value is
- // zero, we can zero all the memory w/out worring about the
- // number of bits per entity.
- if (!default_value || !*default_value)
- memset(mBitArray, 0, mPageSize);
- // Otherwise initialize memory using default value
- else {
- // Mask unused bits of default value so that we can set
- // individual bits using bitwise-OR w/out having to worry
- // about masking unwanted stuff.
- unsigned char defval = (*default_value) & ((1u << num_bits_per_flag) - 1);
-
- switch (num_bits_per_flag) {
- // If number of bits is a power of two (a byte contains a whole
- // number of tag bit values) then use memset to initialize the memory.
- // Note fall-through for switch cases: for 1-bit tags we first
- // copy the lsb into the adjacent bit, then fall through to 2-bit
- // case, copying last two bits into next two, and so on.
- case 1: defval |= (defval << 1);
- case 2: defval |= (defval << 2);
- case 4: defval |= (defval << 4);
- case 8: memset( mBitArray, defval, mPageSize );
- break;
- // If num_bits_per_flag is not a power of two, then values do
- // not align with byte boundaries. Need to initialize values
- // individually.
- default:
- memset(mBitArray, 0, mPageSize);
- // Subtract 1 from mPageSize because last byte is unused, allowing
- // questionable MBBitManipulator code to read/write 1 past end
- // of array.
- for (int i = 0; i < 8 * (mPageSize-1); i += num_bits_per_flag)
- MBBitManipulator::set_bits( i, num_bits_per_flag, defval, mBitArray );
- }
- }
-}
-
-
-MBErrorCode MBBitPageGroup::get_bits( MBEntityHandle start,
- MBEntityID count,
- unsigned char* bits,
- const unsigned char* def_val)
-{
- MBErrorCode result = MB_SUCCESS, tmp_result;
-
-
- MBEntityID id = ID_FROM_HANDLE(start);
- MBEntityHandle page = id/mOffsetFactor;
- MBEntityID offset = id%mOffsetFactor;
- MBEntityID pcount = mOffsetFactor - offset;
- while (count) {
- if (pcount > count)
- pcount = count;
-
- if (page >= mBitPagesSize) {
- memset( bits, def_val ? *def_val : 0, count );
- break;
- }
-
- tmp_result = mBitPages[page]->get_bits( offset, pcount, mBitsPerFlag, bits, def_val);
- if (MB_SUCCESS != tmp_result) {
- memset( bits, 0, pcount );
- result = tmp_result;
- }
-
- count -= pcount;
- bits += pcount;
- ++page;
- offset = 0;
- pcount = mOffsetFactor;
- }
-
- return result;
-}
-
-MBErrorCode MBBitPageGroup::set_bits( MBEntityHandle start,
- MBEntityID count,
- const unsigned char* bits,
- const unsigned char* def_val)
-{
- MBErrorCode result = MB_SUCCESS, tmp_result;
- MBEntityID id = ID_FROM_HANDLE(start);
- MBEntityHandle page = id/mOffsetFactor;
- MBEntityID offset = id%mOffsetFactor;
- MBEntityID pcount = mOffsetFactor - offset;
- while (count) {
- if (pcount > count)
- pcount = count;
-
- if (page >= mBitPagesSize) {
- for(int j = page - mBitPagesSize +1; j--;)
- mBitPages.push_back(new MBBitPage());
- mBitPagesSize = mBitPages.size();
- }
-
- tmp_result = mBitPages[page]->set_bits( offset, pcount, mBitsPerFlag, bits, def_val);
- if (MB_SUCCESS != tmp_result) {
- result = tmp_result;
- }
-
- count -= pcount;
- bits += pcount;
- ++page;
- offset = 0;
- pcount = mOffsetFactor;
- }
-
- return result;
-}
-
-
-MBErrorCode MBBitPageGroup::get_entities_with_value( unsigned char value,
- MBEntityHandle first,
- MBEntityHandle last,
- MBRange& results )
-{
- MBErrorCode rval;
- assert(last >= first);
- MBEntityID count = last - first + 1;
-
- MBEntityID id = ID_FROM_HANDLE(first);
- MBEntityHandle page = id/mOffsetFactor;
- MBEntityID offset = id%mOffsetFactor;
- MBEntityID pcount = mOffsetFactor - offset;
- while (count && page < mBitPagesSize) {
- if (pcount > count)
- pcount = count;
-
- rval = mBitPages[page]->get_entities_with_value( value, offset, pcount, mBitsPerFlag, first, results );
- if (MB_SUCCESS != rval)
- return rval;
-
- first += pcount;
- count -= pcount;
- ++page;
- offset = 0;
- pcount = mOffsetFactor;
- }
-
- return MB_SUCCESS;
-}
-
-MBErrorCode MBBitServer::set_bits( MBTagId tag_id,
- const MBRange& handles,
- const unsigned char* data,
- const unsigned char* default_val)
-{
- --tag_id; // First ID is 1.
- if(tag_id >= mBitPageGroups[0].size() || mBitPageGroups[0][tag_id] == NULL)
- return MB_TAG_NOT_FOUND;
-
- MBErrorCode rval;
- MBRange::const_pair_iterator i;
- for (i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i) {
- MBEntityType type = TYPE_FROM_HANDLE(i->first);
- assert(TYPE_FROM_HANDLE(i->second) == type); // should be true because id of zero is never used
- MBEntityID count = i->second - i->first + 1;
- rval = mBitPageGroups[type][tag_id]->set_bits(i->first, count, data, default_val);
- if (MB_SUCCESS != rval)
- return rval;
- data += count;
- }
- return MB_SUCCESS;
-}
-
-MBErrorCode MBBitServer::get_bits( MBTagId tag_id,
- const MBRange& handles,
- unsigned char* data,
- const unsigned char* default_val)
-{
- --tag_id; // First ID is 1.
- if(tag_id >= mBitPageGroups[0].size() || mBitPageGroups[0][tag_id] == NULL)
- return MB_TAG_NOT_FOUND;
-
- MBErrorCode rval;
- MBRange::const_pair_iterator i;
- for (i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i) {
- MBEntityType type = TYPE_FROM_HANDLE(i->first);
- assert(TYPE_FROM_HANDLE(i->second) == type); // should be true because id of zero is never used
- MBEntityID count = i->second - i->first + 1;
- rval = mBitPageGroups[type][tag_id]->get_bits(i->first, count, data, default_val);
- if (MB_SUCCESS != rval)
- return rval;
- data += count;
- }
- return MB_SUCCESS;
-}
-
-/*! give back a tag id that was used to set and get bits */
-MBErrorCode MBBitServer::release_tag_id(MBTagId tag_id)
-{
- // tag ids begin with 1
- --tag_id;
-
- // make sure tag_id is good
- if(tag_id >= (*mBitPageGroups).size())
- return MB_TAG_NOT_FOUND;
-
- // mark it unused
- for(int i=0; i<(int)MBMAXTYPE; i++)
- {
- delete mBitPageGroups[i][tag_id];
- mBitPageGroups[i][tag_id] = NULL;
- }
-
- // clean up a bit if this is the last one
- if((tag_id+1) == (unsigned short)(*mBitPageGroups).size())
- {
- for(int i=0; i<(int)MBMAXTYPE; i++)
- {
- mBitPageGroups[i].resize(mBitPageGroups[i].size()-1);
- }
- }
-
- mBitPageGroupsSize = (*mBitPageGroups).size();
-
- return MB_SUCCESS;
-}
-
-
-void MBBitServer::reset_data()
-{
- for(int i = 0; i<(int)MBMAXTYPE; i++)
- {
- for (std::vector<MBBitPageGroup*>::iterator iter = mBitPageGroups[i].begin();
- iter != mBitPageGroups[i].end();
- ++iter)
- {
- if(*iter == NULL)
- continue;
- int tag_size = (*iter)->tag_size();
- delete *iter;
- *iter = new MBBitPageGroup(tag_size);
- }
- }
-}
-
-MBErrorCode MBBitServer::get_memory_use( MBTagId tag_id,
- unsigned long& total,
- unsigned long& per_entity ) const
-{
- per_entity = 1; // cannot return fraction of bytes
-
- unsigned max_num_tags = 0;
- for (unsigned i = 0; i < MBMAXTYPE; ++i) {
- if (mBitPageGroups[i].size() > max_num_tags)
- max_num_tags = mBitPageGroups[i].size();
-
- if (tag_id >= mBitPageGroups[i].size())
- continue;
-
- total += mBitPageGroups[i][tag_id]->get_memory_use();
- total += sizeof(MBBitPageGroup*) * mBitPageGroups[i].capacity() / mBitPageGroups[i].size();
- }
- total += sizeof( std::vector<MBBitPageGroup*> );
- total += sizeof(*this) / max_num_tags;
-
- return MB_SUCCESS;
-}
-
-unsigned long MBBitPageGroup::get_memory_use() const
-{
- unsigned long result = sizeof(*this);
- result += sizeof(MBBitPage*) * mBitPages.capacity();
- for (unsigned long i = 0; i < mBitPages.size(); ++i)
- if (mBitPages[i] && mBitPages[i]->has_data())
- result += MBBitPage::mPageSize;
- return result;
-}
-
-//! get the entities
-MBErrorCode MBBitPageGroup::get_entities(MBEntityType type, MBRange& entities)
-{
- std::vector<MBBitPage*>::iterator iter;
- int dum =0;
- MBEntityHandle handle = CREATE_HANDLE(type, MB_START_ID, dum);
- bool first_time = true;
- for(iter = mBitPages.begin(); iter < mBitPages.end(); ++iter)
- {
- if(*iter)
- {
- if((*iter)->has_data())
- {
- entities.insert(handle, handle + mOffsetFactor);
- }
- }
- if(first_time)
- {
- first_time = false;
- handle = handle + mOffsetFactor - MB_START_ID;
- }
- else
- handle += mOffsetFactor;
- }
- return MB_SUCCESS;
-}
-
-MBErrorCode MBBitServer::get_entities(const MBRange &range, MBTagId tag_id, MBEntityType type,
- MBRange& entities)
-{
- --tag_id;
- if(tag_id >= mBitPageGroupsSize || (*mBitPageGroups)[tag_id] == NULL)
- return MB_FAILURE;
-
- MBRange dum_range;
- MBErrorCode result = mBitPageGroups[type][tag_id]->get_entities(type, dum_range);
- if (MB_FAILURE == result) return result;
-
- std::set_intersection(dum_range.begin(), dum_range.end(),
- range.begin(), range.end(),
- mb_range_inserter(entities));
-
- return result;
-}
-
-MBErrorCode MBBitServer::get_entities_with_tag_value( MBTagId tag_id,
- MBEntityType type,
- MBRange& entities,
- const unsigned char bits)
-{
- --tag_id; // First ID is 1.
- if(tag_id >= mBitPageGroups[type].size() || mBitPageGroups[type][tag_id] == NULL)
- return MB_TAG_NOT_FOUND;
-
- return mBitPageGroups[type][tag_id]->
- get_entities_with_value( bits, FIRST_HANDLE(type), LAST_HANDLE(type), entities );
-}
-
-MBErrorCode MBBitServer::get_entities_with_tag_value( const MBRange &range,
- MBTagId tag_id,
- MBEntityType type,
- MBRange& entities,
- const unsigned char bits)
-{
- --tag_id; // First ID is 1.
- if(tag_id >= mBitPageGroups[0].size() || mBitPageGroups[0][tag_id] == NULL)
- return MB_TAG_NOT_FOUND;
-
- MBErrorCode rval;
- MBRange::const_pair_iterator i;
- for (i = range.const_pair_begin(); i != range.const_pair_end(); ++i) {
- MBEntityType this_type = TYPE_FROM_HANDLE(i->first);
- assert(TYPE_FROM_HANDLE(i->second) == this_type); // should be true because id of zero is never used
- if (type < this_type)
- continue;
- if (type > this_type)
- break;
-
- rval = mBitPageGroups[type][tag_id]->
- get_entities_with_value( bits, i->first, i->second, entities );
- if (MB_SUCCESS != rval)
- return rval;
- }
- return MB_SUCCESS;
-}
-
-MBErrorCode MBBitServer::get_number_entities( const MBTagId tag_id,
- const MBEntityType type,
- int& num_entities)
-{
- MBRange dum_range;
- MBErrorCode result = get_entities(tag_id, type, dum_range);
- num_entities = dum_range.size();
- return result;
-}
-
-
-MBErrorCode MBBitServer::get_number_entities( const MBRange &range,
- const MBTagId tag_id,
- const MBEntityType type,
- int& num_entities)
-{
- MBRange dum_range;
- MBErrorCode result = get_entities(range, tag_id, type, dum_range);
- num_entities = dum_range.size();
- return result;
-}
-
-#ifdef BIT_MANIP_TEST
-
-int main()
-{
-
- unsigned char arr[10] = { 0 };
-
- unsigned char bits=0;
-
- MBBitManipulator::set_bits(7, 2, 0x3, arr);
-
- bits = MBBitManipulator::get_bits(6, 3, arr);
-
-
- return 0;
-}
-
-
-#endif
-
-
-// unit test
-#ifdef TEST
-
-#include <stdio.h>
-#include <assert.h>
-
-int main()
-{
-
- MBBitServer bit_server;
- MBTagId tag_id;
- bit_server.reserve_tag_id(5, tag_id);
- unsigned char bits;
- bit_server.get_bits(tag_id, 400, bits);
- assert(bits == 0x0);
-
- bit_server.set_bits(tag_id, 600, 0x9);
- bit_server.get_bits(tag_id, 600, bits);
- assert(bits == 0x9);
-
- //bit_server.release_tag_id(tag_id);
-
- srand(0xb);
-
- for(int i=100; i--; )
- {
- int num_bits = rand() % 9;
- if(bit_server.reserve_tag_id(num_bits, tag_id) == MB_SUCCESS)
- {
- for(int j=1000; j--;)
- {
- unsigned short handle = rand();
- unsigned char some_bits = rand();
- some_bits <<= 8-num_bits;
- some_bits >>= 8-num_bits;
- bit_server.set_bits(tag_id, handle, some_bits);
- unsigned char some_bits_again = rand();
- bit_server.get_bits(tag_id, handle, some_bits_again);
- if(some_bits_again != some_bits)
- {
- bit_server.get_bits(tag_id, handle, some_bits_again);
- printf("ERROR\n num bits = %i\n", num_bits);
- printf( " tag id %i\n", tag_id);
- printf( " handle %u\n", handle);
- printf( " set value %i\n", (int)some_bits);
- printf( " get value %i\n", (int)some_bits_again);
- assert(some_bits_again == some_bits);
- }
- }
-
- bit_server.release_tag_id(tag_id);
- }
- }
- return 0;
-}
-
-#endif
-
-
Deleted: MOAB/trunk/MBBits.hpp
===================================================================
--- MOAB/trunk/MBBits.hpp 2009-11-30 23:06:35 UTC (rev 3389)
+++ MOAB/trunk/MBBits.hpp 2009-11-30 23:07:51 UTC (rev 3390)
@@ -1,710 +0,0 @@
-/**
- * MOAB, a Mesh-Oriented datABase, is a software component for creating,
- * storing and accessing finite element mesh data.
- *
- * Copyright 2004 Sandia Corporation. Under the terms of Contract
- * DE-AC04-94AL85000 with Sandia Coroporation, the U.S. Government
- * retains certain rights in this software.
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- */
-
-
-/* Bit tools for MB
- *
- * File : MBBits.hpp
- * Creator: Clinton Stimpson
- * Date : 10-10-2002
- */
-
-#ifndef MB_BITS_HPP
-#define MB_BITS_HPP
-
-#ifndef IS_BUILDING_MB
-#error "MBBits.hpp isn't supposed to be included into an application"
-#endif
-
-#include "MBForward.hpp"
-#include "MBInternals.hpp"
-
-#include <assert.h>
-#include <string.h>
-
-//! bit manipulator class
-class MBBitManipulator
-{
-public:
-
- //! set bits from value into bit array given an offset and bits per offset
- static MBErrorCode set_bits(int bit_offset, int num_bits,
- unsigned char value, unsigned char* bit_array );
-
- //! gets bits from bit_array given an offset and bits per offset
- static unsigned char get_bits(int bit_offset, int num_bits,
- unsigned char* bit_array );
-
- // bit_array example
- //
- // 010101010101001100100111010010101010010111001010
- // char \1 byte/\1 byte/\1 byte/\1 byte/\1 byte/\1 byte/
- // 3 bits per flag \1/\2/\3/\4/\5/\6/\7/\8/\9/\./\./\./\./\./\./
- //
- // lets offset 5 and get those bits
- // int x = get_bits( 5, 3, char_array )
- // bits returned are 001
- //
- // Assumptions made by this class:
- // num_bits is 8 or less, if it is greater, there is no guarantee
- // you'll get what you want.
-
-private:
-
- //! quick mod 8 operation for finding out how far some bits
- //! are from a byte boundary
- static int mod_8(int val)
- {
- return val & 0x7;
- }
-
- // stores the masks indexed by how many bits to mask
- static const unsigned int masks[9];
-};
-
-/*! set the bits in an array
- takes bit_offset which is the ith bit in the array
- takes num_bits which is number of bits from the ith bit to set
- takes value which is the value to set
- takes_byte array which is the array of bits
-*/
-inline MBErrorCode MBBitManipulator::set_bits(
- int bit_offset,
- int num_bits,
- unsigned char value,
- unsigned char* byte_array
- )
-{
-
- // check the value to make sure it is good
- if((value | masks[num_bits]) != masks[num_bits])
- return MB_FAILURE;
-
- // offset our pointer to where we want it
- byte_array += bit_offset/8;
-
- // copy data from two bytes into our unsigned short
- unsigned short int old_data = *(byte_array +1) << 8;
- old_data += *byte_array;
-
- // shift the value so it is lined up with word boundary of bit array
- unsigned short int aligned_value = value << mod_8(bit_offset);
-
- // shift the mask where we need it
- unsigned short int aligned_mask = masks[num_bits] << mod_8(bit_offset);
-
- // AND aligned_ask and byte_bound to preserve bits that are on
- unsigned short int x = (~aligned_mask) & old_data;
-
- // OR to set value
- old_data = x | aligned_value;
-
- // set the data
- *byte_array = (old_data & 0xFF);
- *(byte_array + 1) = (old_data >> 8);
-
- return MB_SUCCESS;
-}
-
-/*! get the bits in an array
- takes bit_offset which is the ith bit in the array
- takes num_bits which is number of bits from the ith bit to get
- takes_byte array which is the array of bits
- return the bits
-*/
-inline unsigned char MBBitManipulator::get_bits(
- int bit_offset,
- int num_bits,
- unsigned char* byte_array
- )
-{
- // offset our pointer to where we want it
- byte_array += bit_offset/8;
-
- // copy data from two bytes into our unsigned short
- unsigned short int data = *(byte_array +1) << 8;
- data += *byte_array;
-
- // shift data where we need it
- unsigned int aligned_data = data >> mod_8(bit_offset);
-
- // AND caputures value of the flag
- return aligned_data & masks[num_bits];
-}
-
-
-//! bit page class
-/*! This class stores a page of memory for storing bits
-*/
-class MBBitPage
-{
-
-public:
-
- //! the page size
- static const int mPageSize;
-
- // page sizes are 512 bytes
- // for 1 bit per entity, that is 4096 bit flags
- // for 2 bits per entity, that is 2048 bit flags
- // for 3 bits per entity, that is 1365.333 bit flags
- // for 4 bits per entity, that is 1024 bit flags
- // for 5 bits per entity, that is 819.2 bit flags
- // for 6 bits per entity, that is 682.666 bit flags
- // for 7 bits per entity, that is 585.142857
- // for 8 bits per entity, that is 512 bit flags
- //
- // for some, we'll have left over bits on the end.
-
- // default constructor
- MBBitPage() : mBitArray(NULL) {}
-
- // default destructor
- ~MBBitPage()
- {
- if(mBitArray)
- delete [] mBitArray;
- }
-
- //! get the bits from a bit page
- MBErrorCode get_bits(int offset, int num_bits_per_flag, unsigned char& bits,
- const unsigned char* default_value);
-
- //! set the bits in a bit page
- MBErrorCode set_bits(int offset, int num_bits_per_flag, unsigned char bits,
- const unsigned char* default_value);
-
- //! get the bits from a bit page
- MBErrorCode get_bits(int offset, int count, int num_bits_per_flag,
- unsigned char* bits,
- const unsigned char* default_value);
-
- //! set the bits in a bit page
- MBErrorCode set_bits(int offset, int count, int num_bits_per_flag,
- const unsigned char* bits,
- const unsigned char* default_value);
-
- MBErrorCode get_entities_with_value( unsigned char value,
- int offset,
- int count,
- int num_bits_per_flag,
- MBEntityHandle first,
- MBRange& results ) const;
-
- //! set the bits in a bit page only if space has been allocated
- MBErrorCode weak_set_bits(int offset, int num_bits_per_flag, unsigned char bits);
-
- bool has_data() const { return mBitArray != NULL; }
-
-private:
- //! bit array uses lazy allocation
- unsigned char* mBitArray;
-
- void alloc_array( int num_bits_per_flag, const unsigned char* default_value );
-
- //! don't allow copying of these bit pages
- MBBitPage(const MBBitPage&)
- : mBitArray(NULL)
- {
- // not even by self
- assert(0);
- }
-
- //! don't allow copying of these bit pages
- MBBitPage& operator=(const MBBitPage&)
- {
- // not even by self
- assert(0);
- return *this;
- }
-
-};
-
-/*! get the bits from a bit page
- takes bit offset into the page
- takes how many bits to get
- return bits
-*/
-inline MBErrorCode MBBitPage::get_bits(int offset, int num_bits_per_flag,
- unsigned char& bits,
- const unsigned char* def_val)
-{
- // because the default bits are 0x0,
- // we'll return that if no memory has been allocated
- if(!mBitArray)
- {
- bits = def_val ? *def_val : 0;
- return MB_SUCCESS;
- }
-
- // get bits using bit manipulator
- bits = MBBitManipulator::get_bits(
- offset*num_bits_per_flag, num_bits_per_flag, mBitArray);
-
- return MB_SUCCESS;
-}
-inline MBErrorCode MBBitPage::get_bits(int offset, int count,
- int num_bits_per_flag,
- unsigned char* bits,
- const unsigned char* def_val)
-{
- // because the default bits are 0x0,
- // we'll return that if no memory has been allocated
- if(!mBitArray)
- {
- memset( bits, def_val ? *def_val : 0, count );
- return MB_SUCCESS;
- }
-
- // get bits using bit manipulator
- for (int i = 0; i < count; ++i)
- bits[i] = MBBitManipulator::get_bits(
- (offset+i)*num_bits_per_flag, num_bits_per_flag, mBitArray);
-
- return MB_SUCCESS;
-}
-
-
-/*! set the bits in a bit page
- takes bit offset into the page
- takes how many bits to set
- takes the bits to set
-*/
-inline MBErrorCode MBBitPage::set_bits( int offset,
- int num_bits_per_flag,
- unsigned char bits,
- const unsigned char* default_value)
-{
- // if memory hasn't been allocated, allocate it and zero the memory
- if(!mBitArray)
- alloc_array( num_bits_per_flag, default_value );
-
- // set the bits using bit manipulator
- return MBBitManipulator::set_bits(
- offset*num_bits_per_flag, num_bits_per_flag, bits, mBitArray);
-}
-inline MBErrorCode MBBitPage::set_bits( int offset, int count,
- int num_bits_per_flag,
- const unsigned char* bits,
- const unsigned char* default_value)
-{
- // if memory hasn't been allocated, allocate it and zero the memory
- if(!mBitArray)
- alloc_array( num_bits_per_flag, default_value );
-
- // set the bits using bit manipulator
- for (int i = 0; i < count; ++i)
- MBBitManipulator::set_bits( (offset+i)*num_bits_per_flag,
- num_bits_per_flag,
- bits[i], mBitArray );
- return MB_SUCCESS;
-}
-
-
-/*! weak set bits only sets bits if memory has been allocated
- takes bit offset
- takes number of bits to set
- takes the bits to set
-*/
-inline MBErrorCode MBBitPage::weak_set_bits(int offset,
- int num_bits_per_flag, unsigned char bits)
-{
- return mBitArray ? MBBitManipulator::set_bits(
- offset*num_bits_per_flag, num_bits_per_flag, bits, mBitArray) : MB_SUCCESS;
-}
-
-//! class which is a collection of bit pages
-class MBBitPageGroup
-{
-public:
- // default constructor
- MBBitPageGroup(int bits_per_flag)
- : mBitsPerFlag(bits_per_flag)
- {
- //compute the offset factor based on the number of bits for each entity
- //this offset will most likely leave some unused bits at the end of a page
- mOffsetFactor = compute_offset_factor(bits_per_flag);
- mBitPagesSize = 0;
- }
-
- // default destructor
- ~MBBitPageGroup()
- {
- // delete each bit page
- for (std::vector<MBBitPage*>::iterator iter = mBitPages.begin(); iter != mBitPages.end(); ++iter)
- delete *iter;
-
- // clean out the vector of pointers
- mBitPages.clear();
- }
-
- //! get bits from bit pages
- MBErrorCode get_bits(MBEntityHandle handle, unsigned char& bits,
- const unsigned char* default_value);
-
- //! set bits in bit pages
- MBErrorCode set_bits(MBEntityHandle handle, unsigned char bits,
- const unsigned char* default_value);
-
- //! get bits from bit pages
- MBErrorCode get_bits(MBEntityHandle start, MBEntityID count,
- unsigned char* data,
- const unsigned char* default_value);
-
- //! set bits in bit pages
- MBErrorCode set_bits(MBEntityHandle start, MBEntityID count,
- const unsigned char* data,
- const unsigned char* default_value);
-
- //! set bits in bit pages only if the bit page allocated memory
- MBErrorCode weak_set_bits(MBEntityHandle handle, unsigned char bits);
-
- MBErrorCode get_entities(MBEntityType type, MBRange& entities);
-
- MBErrorCode get_entities_with_value( unsigned char value,
- MBEntityHandle first,
- MBEntityHandle last,
- MBRange& results );
-
- //! if this page group contains this entity, return true, otherwise false
- bool contains(const MBEntityHandle handle) const;
-
- int tag_size() const { return mBitsPerFlag; }
-
- unsigned long get_memory_use( ) const;
-
-private:
-
- // compute offset factor to use when computing which page to index into
- int compute_offset_factor(int num_bits)
- {
- // subtract one from page size to prevent reading past
- // the page one byte (BitManipulator does this).
- // this results in one byte at the end of the page
- // that isn't used, but that's no big deal.
- return (MBBitPage::mPageSize - 1) * 8 / num_bits;
- }
-
- //! number of bits for each entity
- unsigned short mBitsPerFlag;
-
- //! offset factor used when computing which page to jump to
- unsigned short mOffsetFactor;
-
- unsigned int mBitPagesSize;
-
- //! vector of bit pages
- std::vector<MBBitPage*> mBitPages;
-
- //! don't allow copy of this class
- MBBitPageGroup& operator=(const MBBitPageGroup&)
- {
- assert(0);
- return *this;
- }
-
- //! don't allow copy of this class
- MBBitPageGroup(const MBBitPageGroup&)
- {
- assert(0);
- }
-
-};
-
-/*! get the bits from bit pages
- takes entity handle
- return the bits
-*/
-inline MBErrorCode MBBitPageGroup::get_bits(MBEntityHandle handle,
- unsigned char& bits,
- const unsigned char* def_val)
-{
- // strip off the entity type
- handle = ID_FROM_HANDLE(handle);
- // figure out which page to jump to
- unsigned int which_page = handle / mOffsetFactor;
-
- // if the page isn't there, just return 0x0
- if(which_page >= mBitPagesSize) {
- bits = def_val ? *def_val : 0;
- return MB_SUCCESS;
- }
-
- // return bits from bit page
- return mBitPages[which_page]->get_bits( (handle - ( which_page * mOffsetFactor )),
- mBitsPerFlag, bits, def_val);
-}
-
-/*! set the bits in bit pages
- takes entity handle
- takes the bits to set
-*/
-inline MBErrorCode MBBitPageGroup::set_bits( MBEntityHandle handle,
- unsigned char bits,
- const unsigned char* default_value )
-{
- // strip off the entity type
- handle = ID_FROM_HANDLE(handle);
- // figure out which page to jump to
- unsigned int which_page = handle / mOffsetFactor;
-
- // if the page doesn't exist, make one
- if(which_page >= mBitPagesSize)
- {
- for(int j= which_page - mBitPagesSize +1; j--;)
- mBitPages.push_back(new MBBitPage());
- mBitPagesSize = mBitPages.size();
- }
-
- // return set of bits in page
- return mBitPages[which_page]->
- set_bits( (handle - ( which_page * mOffsetFactor )),
- mBitsPerFlag, bits, default_value );
-}
-
-
-/*! set the bits in bit pages
- if the page didn't allocate memory yet, the bits aren't set
- takes entity handle
- takes the bits to set
-*/
-inline MBErrorCode MBBitPageGroup::weak_set_bits(MBEntityHandle handle, unsigned char bits)
-{
- // strip off entity type
- handle = ID_FROM_HANDLE(handle);
- // find out which page to jump to
- unsigned int which_page = handle / mOffsetFactor;
-
- // if the page doesn't exist, return
- if(which_page >= mBitPagesSize)
- return MB_SUCCESS;
-
- // try to set bits
- return mBitPages[which_page]->weak_set_bits( (handle - ( which_page * mOffsetFactor )), mBitsPerFlag, bits);
-}
-
-inline bool MBBitPageGroup::contains(const MBEntityHandle handle) const
-{
- // strip off the entity type
- unsigned int entity_id = ID_FROM_HANDLE(handle);
- // figure out which page to jump to
- unsigned int which_page = entity_id / mOffsetFactor;
-
- // if the page isn't there, just return 0x0
- return (which_page >= mBitPagesSize ? false : true);
-}
-
-//! MBBitServer class provides constant time
-//! lookup for bit flags tagged on entities
-class MBBitServer
-{
-public:
- //! default constructor
- MBBitServer()
- {
- mBitPageGroupsSize = 0;
- }
- //! default destructor
- ~MBBitServer()
- {
- // clean things out
- for(int i = 0; i<(int)MBMAXTYPE; i++)
- {
- for (std::vector<MBBitPageGroup*>::iterator iter = mBitPageGroups[i].begin();
- iter != mBitPageGroups[i].end();
- ++iter)
- {
- if(*iter == NULL)
- continue;
- delete *iter;
- }
-
- mBitPageGroups[i].clear();
- }
- }
-
- void reset_data();
-
- //! allocate data for tag with specified ID
- MBErrorCode reserve_tag_id(int num_bits, MBTagId tag_id);
- //! release a tag id for reuse
- MBErrorCode release_tag_id(MBTagId tag_id);
-
- //! get the bits associated with entity handles
- MBErrorCode get_bits(MBTagId tag_id,
- const MBEntityHandle* handles,
- int num_handles,
- unsigned char* data,
- const unsigned char* default_value);
- MBErrorCode get_bits(MBTagId tag_id,
- const MBRange& handles,
- unsigned char* data,
- const unsigned char* default_value);
- //! set the bits associated with an entity handle
- MBErrorCode set_bits(MBTagId tag_id,
- const MBEntityHandle* handles,
- int num_handles,
- const unsigned char* data,
- const unsigned char* default_value);
- MBErrorCode set_bits(MBTagId tag_id,
- const MBRange& handles,
- const unsigned char* data,
- const unsigned char* default_value);
- //! set the bits associated with an entity handle, only if memory has been allocated
- MBErrorCode weak_set_bits(MBTagId tag_id, MBEntityHandle handle, unsigned char bits);
-
- //! clear bits
- MBErrorCode clear_bits( MBTagId tag_id, MBEntityHandle handle, const unsigned char* defval )
- { return weak_set_bits( tag_id, handle, defval ? *defval : '\0' ); }
-
- MBErrorCode get_entities(MBTagId tag_id, MBRange& entities);
-
- MBErrorCode get_entities(MBTagId tag_id, MBEntityType type, MBRange& entities);
-
- MBErrorCode get_entities_with_tag_value(MBTagId tag_id,
- MBEntityType type,
- MBRange& entities,
- const unsigned char bits);
-
- MBErrorCode get_entities(const MBRange &range,
- MBTagId tag_id,
- MBEntityType type,
- MBRange& entities);
-
- MBErrorCode get_entities_with_tag_value(const MBRange &range,
- MBTagId tag_id, MBEntityType type,
- MBRange& entities,
- const unsigned char bits);
-
- //! get all tags defined on an entity
- MBErrorCode get_tags(const MBEntityHandle entity,
- std::vector<MBTag> &tags);
-
- MBErrorCode get_number_entities(const MBTagId tag_id,
- const MBEntityType type,
- int& num_entities);
-
- MBErrorCode get_number_entities( const MBRange &range,
- const MBTagId tag_id,
- const MBEntityType type,
- int& num_entities);
-
- MBErrorCode get_memory_use( MBTagId tag,
- unsigned long& total,
- unsigned long& per_entity ) const;
-private:
- //! bit pages are indexed by tag id and entity type
- std::vector< MBBitPageGroup* > mBitPageGroups[MBMAXTYPE];
- unsigned long mBitPageGroupsSize;
-
-};
-
-/*! get some bits based on a tag id and handle */
-inline
-MBErrorCode MBBitServer::get_bits( MBTagId tag_id,
- const MBEntityHandle* handles,
- int num_handles,
- unsigned char* data,
- const unsigned char* default_val)
-{
- --tag_id; // First ID is 1.
- if(tag_id >= mBitPageGroups[0].size() || mBitPageGroups[0][tag_id] == NULL)
- return MB_TAG_NOT_FOUND;
-
- MBErrorCode rval;
- for (int i = 0; i < num_handles; ++i) {
- rval = mBitPageGroups[TYPE_FROM_HANDLE(handles[i])][tag_id]
- ->get_bits(handles[i], data[i], default_val);
- if (MB_SUCCESS != rval)
- return rval;
- }
- return MB_SUCCESS;
-}
-
-inline
-MBErrorCode MBBitServer::set_bits( MBTagId tag_id,
- const MBEntityHandle* handles,
- int num_handles,
- const unsigned char* data,
- const unsigned char* default_val)
-{
- --tag_id; // First ID is 1.
- if(tag_id >= mBitPageGroups[0].size() || mBitPageGroups[0][tag_id] == NULL)
- return MB_TAG_NOT_FOUND;
-
- MBErrorCode rval;
- for (int i = 0; i < num_handles; ++i) {
- rval = mBitPageGroups[TYPE_FROM_HANDLE(handles[i])][tag_id]
- ->set_bits(handles[i], data[i], default_val);
- if (MB_SUCCESS != rval)
- return rval;
- }
- return MB_SUCCESS;
-}
-
-/*! set some bits based on a tag id and handle only if memory has been allocated*/
-inline MBErrorCode MBBitServer::weak_set_bits(MBTagId tag_id,
- MBEntityHandle handle, unsigned char bits)
-{
- --tag_id; // First ID is 1.
- if(tag_id >= mBitPageGroupsSize || (*mBitPageGroups)[tag_id] == NULL)
- return MB_SUCCESS;
-
- return mBitPageGroups[TYPE_FROM_HANDLE(handle)][tag_id]->weak_set_bits(handle, bits);
-}
-
-inline MBErrorCode MBBitServer::get_entities(MBTagId tag_id, MBRange& entities)
-{
- --tag_id; // First ID is 1.
- MBErrorCode result = MB_SUCCESS;
- if(tag_id >= mBitPageGroupsSize || (*mBitPageGroups)[tag_id] == NULL)
- result = MB_FAILURE;
- else {
- for (MBEntityType type = MBVERTEX; type != MBMAXTYPE; type++) {
- MBErrorCode tmp_result = mBitPageGroups[type][tag_id]->get_entities(type, entities);
- if (MB_SUCCESS != tmp_result) result = tmp_result;
- }
- }
-
- return result;
-}
-
-inline MBErrorCode MBBitServer::get_entities(MBTagId tag_id, MBEntityType type, MBRange& entities)
-{
- --tag_id; // First ID is 1.
- if(tag_id >= mBitPageGroupsSize || (*mBitPageGroups)[tag_id] == NULL)
- return MB_FAILURE;
-
- return mBitPageGroups[type][tag_id]->get_entities(type, entities);
-}
-
- //! get all tags defined on an entity
-inline MBErrorCode MBBitServer::get_tags(const MBEntityHandle entity,
- std::vector<MBTag> &tags)
-{
- // get the tags defined for this type
- MBEntityType this_type = TYPE_FROM_HANDLE(entity);
-
- for (long i = 0; i < (long) mBitPageGroups[this_type].size(); i++) {
- if (mBitPageGroups[this_type][i] != NULL &&
- mBitPageGroups[this_type][i]->contains(entity))
- tags.push_back(TAG_HANDLE_FROM_ID(i+1, MB_TAG_BIT));
- }
- return MB_SUCCESS;
-}
-
-#endif
-
-
Modified: MOAB/trunk/Makefile.am
===================================================================
--- MOAB/trunk/Makefile.am 2009-11-30 23:06:35 UTC (rev 3389)
+++ MOAB/trunk/Makefile.am 2009-11-30 23:07:51 UTC (rev 3390)
@@ -112,6 +112,8 @@
libMOAB_la_SOURCES = \
AEntityFactory.cpp \
AEntityFactory.hpp \
+ BitTagServer.cpp \
+ BitTagServer.hpp \
DualTool.cpp \
ElementSequence.hpp \
EntitySequence.cpp \
@@ -135,8 +137,6 @@
MBAlloc.hpp \
MBAxisBox.cpp \
MBAxisBox.hpp \
- MBBits.cpp \
- MBBits.hpp \
MBBSPTree.cpp \
MBCN.cpp \
MBCNArrays.hpp \
Modified: MOAB/trunk/TagServer.cpp
===================================================================
--- MOAB/trunk/TagServer.cpp 2009-11-30 23:06:35 UTC (rev 3389)
+++ MOAB/trunk/TagServer.cpp 2009-11-30 23:07:51 UTC (rev 3390)
@@ -41,7 +41,7 @@
#include "TagServer.hpp"
#include "MBRange.hpp"
#include "SparseTagSuperCollection.hpp"
-#include "MBBits.hpp"
+#include "BitTagServer.hpp"
#include "MBInterface.hpp"
#include "SequenceManager.hpp"
#include "TagCompare.hpp"
@@ -65,7 +65,7 @@
: sequenceManager(seqman)
{
mSparseData = new SparseTagSuperCollection;
- mBitServer = new MBBitServer;
+ mBitServer = new BitTagServer;
}
TagServer::~TagServer()
@@ -207,8 +207,9 @@
for (tag_id = 1; tag_id <= mTagTable[MB_TAG_BIT].size(); ++tag_id)
if (mTagTable[MB_TAG_BIT][tag_id-1].is_valid())
- // default data for bits is zero
- mBitServer->weak_set_bits( tag_id, entity_handle, 0 );
+ mBitServer->clear_bits( tag_id, &entity_handle, 1,
+ reinterpret_cast<const unsigned char*>
+ (mTagTable[MB_TAG_DENSE][tag_id-1].default_value()) );
for (tag_id = 1; tag_id <= mTagTable[MB_TAG_SPARSE].size(); ++tag_id)
if (mTagTable[MB_TAG_SPARSE][tag_id-1].is_valid())
@@ -677,7 +678,7 @@
case MB_TAG_SPARSE:
return mSparseData->remove_data(tag_id, entity_handle);
case MB_TAG_BIT:
- return mBitServer->clear_bits( tag_id, entity_handle,
+ return mBitServer->clear_bits( tag_id, &entity_handle, 1,
static_cast<const unsigned char*>(defval) );
case MB_TAG_MESH:
return MB_FAILURE;
Modified: MOAB/trunk/TagServer.hpp
===================================================================
--- MOAB/trunk/TagServer.hpp 2009-11-30 23:06:35 UTC (rev 3389)
+++ MOAB/trunk/TagServer.hpp 2009-11-30 23:07:51 UTC (rev 3390)
@@ -45,7 +45,7 @@
class MBRange;
class SparseTagSuperCollection;
class SequenceManager;
-class MBBitServer;
+class BitTagServer;
//! SparseTagServer class which associates tag data with entities
class TagServer
@@ -327,7 +327,7 @@
SequenceManager* sequenceManager;
//! manager for the bit data
- MBBitServer* mBitServer;
+ BitTagServer* mBitServer;
};
1
0
Author: tautges
Date: 2009-11-30 17:06:35 -0600 (Mon, 30 Nov 2009)
New Revision: 3389
Modified:
MOAB/trunk/MBParallelConventions.h
MOAB/trunk/MBSkinner.cpp
MOAB/trunk/parallel/MBParallelComm.cpp
MOAB/trunk/parallel/MBParallelComm.hpp
MOAB/trunk/parallel/mbparallelcomm_test.cpp
MOAB/trunk/parallel/pcomm_serial.cpp
MOAB/trunk/parallel/pcomm_unit.cpp
MOAB/trunk/tools/iMesh/iMeshP_unit_tests.cpp
Log:
Fairly major changes to parallel ghosting. First, implemented a handshaking approach for
exchanging large messages; this guarantees that a buffer will be allocated and ready
when a large message arrives. Second, implementing an abstract Buffer object (in this case,
a class in MBParallelComm) for buffering. This provides more explicit control over memory
management in buffers, and makes it easier to debug memory access problems. One shortcoming
of the current code is that there's an MPI_Barrier call between sending/receiving entities and
sending/receiving remote handles. I'll try and eliminate this after parallel testing. I'm also
sure there are plenty of places where this code can be cleaned up and made more bulletproof,
and where comments need to be added/improved.
With this commit, parallel ghost exchange now works for all the serial tests I've run so far.
Next up is to start running parallel and timing tests. A couple of the iMeshP tests still fail also.
Specific changes:
MBSkinner: fix problem causing scdtest to die
MBParallelConventions.h: inserted clarifying comment
pcomm_serial: requesting ghosting using faces as bridge entities
pcomm_unit, mbparallelcomm_test: updated to use new buffering scheme
MBParallelComm: many changes summarized in first part of message
iMeshP_unit_tests.cpp: adding PARTITION option
Modified: MOAB/trunk/MBParallelConventions.h
===================================================================
--- MOAB/trunk/MBParallelConventions.h 2009-11-25 21:22:39 UTC (rev 3388)
+++ MOAB/trunk/MBParallelConventions.h 2009-11-30 23:06:35 UTC (rev 3389)
@@ -83,6 +83,7 @@
#define PSTATUS_SHARED 0x2
#define PSTATUS_MULTISHARED 0x4
#define PSTATUS_INTERFACE 0x8
+// note, these numbers are in hex, so 0x10 is the 4th bit, or 2^4.
#define PSTATUS_GHOST 0x10
#define PSTATUS_AND 0x1
Modified: MOAB/trunk/MBSkinner.cpp
===================================================================
--- MOAB/trunk/MBSkinner.cpp 2009-11-25 21:22:39 UTC (rev 3388)
+++ MOAB/trunk/MBSkinner.cpp 2009-11-30 23:06:35 UTC (rev 3389)
@@ -1261,8 +1261,9 @@
MBEntityType type = TYPE_FROM_HANDLE(elem), tmp_type;
const int ncorner = MBCN::VerticesPerEntity( side_type );
const int d = MBCN::Dimension(side_type);
+ std::vector<MBEntityHandle> storage;
- rval = thisMB->get_connectivity( elem, conn, len, false );
+ rval = thisMB->get_connectivity( elem, conn, len, false, &storage );
if (MB_SUCCESS != rval) return rval;
MBCN::SideNumber( type, conn, side_conn, ncorner, d, side, sense, offset );
Modified: MOAB/trunk/parallel/MBParallelComm.cpp
===================================================================
--- MOAB/trunk/parallel/MBParallelComm.cpp 2009-11-25 21:22:39 UTC (rev 3388)
+++ MOAB/trunk/parallel/MBParallelComm.cpp 2009-11-30 23:06:35 UTC (rev 3389)
@@ -43,7 +43,8 @@
#include "MBmpi.h"
#endif
-const unsigned int INITIAL_BUFF_SIZE = 1024;
+const unsigned int MBParallelComm::INITIAL_BUFF_SIZE = 1024;
+
const int MAX_BCAST_SIZE = (1<<28);
#undef DEBUG_MPE
@@ -62,6 +63,12 @@
//#define DEBUG_COMM 1
#undef DEBUG_PACKING
#undef DEBUG_MSGS
+//#define DEBUG_MSGS 1
+#undef DEBUG_BARRIER
+#define DEBUG_BARRIER 1
+#ifdef DEBUG_MSGS
+std::vector<MBParallelComm::Buffer*> msgs;
+#endif
#ifdef DEBUG_PACKING
unsigned int __PACK_num = 0, __UNPACK_num = 0, __PACK_count = 0, __UNPACK_count = 0;
std::string __PACK_string, __UNPACK_string;
@@ -199,31 +206,67 @@
}
}
-template <typename T> static inline
-void CHECK_BUFF_SPACE( std::vector<T>& buff_vec,
- T*& buff_ptr,
- size_t addl_space )
+enum MBMessageTag {MB_MESG_ANY=MPI_ANY_TAG,
+ MB_MESG_ENTS_ACK,
+ MB_MESG_ENTS_SIZE,
+ MB_MESG_ENTS_LARGE,
+ MB_MESG_REMOTEH_ACK,
+ MB_MESG_REMOTEH_SIZE,
+ MB_MESG_REMOTEH_LARGE,
+ MB_MESG_TAGS_ACK,
+ MB_MESG_TAGS_SIZE,
+ MB_MESG_TAGS_LARGE};
+
+static inline size_t RANGE_SIZE(const MBRange& rng)
+ { return 2*sizeof(MBEntityHandle)*rng.psize()+sizeof(int); }
+
+static inline void PRINT_DEBUG_ISEND(int from, int to, unsigned char *buff,
+ int tag, int size)
{
- size_t old_size = buff_ptr - &buff_vec[0];
- size_t new_size = old_size + addl_space;
- if (new_size > buff_vec.size()) {
- buff_vec.resize(1.5*new_size);
- buff_ptr = &buff_vec[old_size];
- }
+#ifdef DEBUG_COMM
+ std::cerr << "Isend, " << from << "->" << to
+ << ", buffer ptr = " << (void*)buff << ", tag=" << tag
+ << ", size=" << size << std::endl; std::cerr.flush();
+#endif
}
-template<typename T> static inline
-void INIT_BUFFER(std::vector<T>& buff_vec, T*& buff_ptr)
+static inline void PRINT_DEBUG_IRECV(int to, int from, unsigned char *buff, int size,
+ int tag, int incoming)
{
- buff_vec.reserve(INITIAL_BUFF_SIZE);
- buff_vec.resize(sizeof(int));
- buff_ptr = &buff_vec[sizeof(int)];
+#ifdef DEBUG_COMM
+ std::cerr << "Irecv, " << to << "<-" << from << ", buffer ptr=" << (void*)buff
+ << ", size=" << size << ", tag=" << tag
+ << (tag < MB_MESG_REMOTEH_ACK ? ", incoming1=" :
+ (tag < MB_MESG_TAGS_ACK ? ", incoming2=" : ", incoming="))
+ << incoming << std::endl; std::cerr.flush();
+#endif
}
+static inline void PRINT_DEBUG_RECD(MPI_Status status)
+{
+#ifdef DEBUG_COMM
+ int this_count;
+ int success = MPI_Get_count(&status, MPI_UNSIGNED_CHAR, &this_count);
+ if (MPI_SUCCESS != success) this_count = -1;
+ std::cerr << "Received from " << status.MPI_SOURCE
+ << ", count = " << this_count
+ << ", tag = " << status.MPI_TAG
+ << std::endl; std::cerr.flush();
+#endif
+}
-static inline size_t RANGE_SIZE(const MBRange& rng)
- { return 2*sizeof(MBEntityHandle)*rng.psize()+sizeof(int); }
+static inline void PRINT_DEBUG_WAITANY(std::vector<MPI_Request> &reqs, int tag, int proc)
+{
+#ifdef DEBUG_COMM
+ std::cerr << "Waitany, p=" << proc
+ << (tag < MB_MESG_REMOTEH_ACK ? ", recv_ent_reqs = " :
+ (tag < MB_MESG_TAGS_ACK ? ", recv_remoteh_reqs = " : ", recv_tag_reqs = "));
+ for (unsigned int i = 0; i < reqs.size(); i++) std::cerr << " " << reqs[i];
+ std::cerr << std::endl; std::cerr.flush();
+#endif
+}
+
#define RR(a) if (MB_SUCCESS != result) {\
dynamic_cast<MBCore*>(mbImpl)->get_error_handler()->set_last_error(a);\
return result;}
@@ -259,14 +302,6 @@
#define PARALLEL_COMM_TAG_NAME "__PARALLEL_COMM"
-enum MBMessageTag {MB_MESG_ANY=MPI_ANY_TAG,
- MB_MESG_ENTS,
- MB_MESG_ENTS_SECOND,
- MB_MESG_REMOTE_HANDLES,
- MB_MESG_REMOTE_HANDLES_SECOND,
- MB_MESG_TAGS,
- MB_MESG_TAGS_SECOND};
-
MBParallelComm::MBParallelComm(MBInterface *impl, MPI_Comm comm, int* id )
: mbImpl(impl), procConfig(comm),
sharedpTag(0), sharedpsTag(0),
@@ -297,6 +332,7 @@
MBParallelComm::~MBParallelComm()
{
remove_pcomm(this);
+ delete_all_buffers();
}
void MBParallelComm::initialize()
@@ -317,8 +353,8 @@
// reserve space for vectors
buffProcs.reserve(MAX_SHARING_PROCS);
- ownerSBuffs.reserve(MAX_SHARING_PROCS);
- ghostRBuffs.reserve(MAX_SHARING_PROCS);
+ localOwnedBuffs.reserve(MAX_SHARING_PROCS);
+ remoteOwnedBuffs.reserve(MAX_SHARING_PROCS);
pcommID = add_pcomm(this);
}
@@ -446,8 +482,8 @@
if (vit == buffProcs.end()) {
ind = buffProcs.size();
buffProcs.push_back((unsigned int)to_proc);
- ownerSBuffs.push_back(std::vector<unsigned char>());
- ghostRBuffs.push_back(std::vector<unsigned char>(INITIAL_BUFF_SIZE));
+ localOwnedBuffs.push_back(new Buffer(INITIAL_BUFF_SIZE));
+ remoteOwnedBuffs.push_back(new Buffer(INITIAL_BUFF_SIZE));
if (is_new) *is_new = true;
}
else {
@@ -458,96 +494,6 @@
return ind;
}
-MBErrorCode MBParallelComm::send_buffer(const unsigned int to_proc,
- const unsigned char *send_buff,
- unsigned int buff_size,
- int mesg_tag,
- MPI_Request &send_req1,
- MPI_Request &send_req2)
-{
- MBErrorCode result = MB_SUCCESS;
- int success;
-
- // size goes on the front
- *((int*)send_buff) = (int)buff_size;
-
- // send the buffer
-#ifdef DEBUG_COMM
- std::cerr << "Isending " << std::min(buff_size, INITIAL_BUFF_SIZE)
- << " bytes to proc " << to_proc
- << " with message tag " << mesg_tag << std::endl;
-#endif
- success = MPI_Isend(const_cast<unsigned char*>(send_buff),
- std::min(buff_size, INITIAL_BUFF_SIZE),
- MPI_UNSIGNED_CHAR, to_proc,
- mesg_tag, procConfig.proc_comm(), &send_req1);
- if (success != MPI_SUCCESS) return MB_FAILURE;
-
- if (buff_size > INITIAL_BUFF_SIZE) {
-#ifdef DEBUG_COMM
- std::cerr << "Isending " << buff_size-INITIAL_BUFF_SIZE
- << " bytes to proc " << to_proc
- << " with message tag " << mesg_tag+1 << "(second)" << std::endl;
-#endif
- success = MPI_Isend(const_cast<unsigned char*>(send_buff+INITIAL_BUFF_SIZE),
- buff_size-INITIAL_BUFF_SIZE,
- MPI_UNSIGNED_CHAR, to_proc,
- mesg_tag+1, procConfig.proc_comm(), &send_req2);
- // put this inside so we can stop on completion in the debugger
- if (success != MPI_SUCCESS) return MB_FAILURE;
- }
-
- return result;
-}
-
-MBErrorCode MBParallelComm::recv_buffer(int mesg_tag_expected,
- const MPI_Status &mpi_status,
- std::vector<unsigned char> &recv_buff,
- MPI_Request &recv_req,
- bool &done)
-{
- // process a received message, possibly posting a receive for the 2nd part of
- // that message
- //
- // if the message comes in with mesg_tag_expected, check the first integer for
- // size; if size is INITIAL_BUFF_SIZE, post a receive for the 2nd message using
- // the same request object, with an offset buffer; otherwise just signal that we're done
- int success;
- if (mpi_status.MPI_TAG == mesg_tag_expected &&
- ((int*)&recv_buff[0])[0] >= (int)INITIAL_BUFF_SIZE) {
- // verify that we received exactly the right number of bytes
-#ifndef NDEBUG
- int this_count;
- success = MPI_Get_count(const_cast<MPI_Status*>(&mpi_status), MPI_UNSIGNED_CHAR,
- &this_count);
- assert(MPI_SUCCESS == success && this_count == (int)INITIAL_BUFF_SIZE);
-#endif
-
- // need to resize to final size, then resubmit irecv pointing to the
- // offset buffer position
- recv_buff.resize(*((int*)&recv_buff[0]));
-
-#ifdef DEBUG_COMM
- std::cout << "Posting Irecv from " << mpi_status.MPI_SOURCE
- << " for 2nd message." << std::endl;
-#endif
-
- int success = MPI_Irecv(&recv_buff[INITIAL_BUFF_SIZE], recv_buff.size()-INITIAL_BUFF_SIZE,
- MPI_UNSIGNED_CHAR, mpi_status.MPI_SOURCE,
- mesg_tag_expected+1, procConfig.proc_comm(), &recv_req);
- if (MPI_SUCCESS != success) {
- MBErrorCode result = MB_FAILURE;
- RRA("Failed call to Irecv in recv_buffer.");
- }
- done = false;
- }
- else {
- done = true;
- }
-
- return MB_SUCCESS;
-}
-
MBErrorCode MBParallelComm::broadcast_entities( const int from_proc,
MBRange &entities,
const bool adjacencies,
@@ -560,16 +506,19 @@
MBErrorCode result = MB_SUCCESS;
int success;
int buff_size;
-
- std::vector<unsigned char> buff;
- std::vector<int> addl_procs;
+
+ Buffer buff(INITIAL_BUFF_SIZE);
+ buff.reset_ptr(sizeof(int));
if ((int)procConfig.proc_rank() == from_proc) {
result = add_verts(entities);
RRA("Failed to add adj vertices.");
+ buff.reset_ptr(sizeof(int));
result = pack_buffer( entities, adjacencies, tags,
- false, -1, buff, buff_size);
+ false, -1, &buff);
RRA("Failed to compute buffer size in broadcast_entities.");
+ buff.set_stored_size();
+ buff_size = buff.buff_ptr - buff.mem_ptr;
}
success = MPI_Bcast( &buff_size, 1, MPI_INT, from_proc, procConfig.proc_comm() );
@@ -582,12 +531,12 @@
return MB_SUCCESS;
if ((int)procConfig.proc_rank() != from_proc)
- buff.resize(buff_size);
+ buff.reserve(buff_size);
size_t offset = 0;
while (buff_size) {
int size = std::min( buff_size, MAX_BCAST_SIZE );
- success = MPI_Bcast( &buff[offset], size, MPI_UNSIGNED_CHAR, from_proc, procConfig.proc_comm() );
+ success = MPI_Bcast(buff.mem_ptr+offset, size, MPI_UNSIGNED_CHAR, from_proc, procConfig.proc_comm() );
if (MPI_SUCCESS != success) {
result = MB_FAILURE;
RRA("MPI_Bcast of buffer failed.");
@@ -602,7 +551,8 @@
std::vector<std::vector<int> > dum1p;
std::vector<MBEntityHandle> dum2;
std::vector<unsigned int> dum3;
- result = unpack_buffer(&buff[0], false, from_proc, -1,
+ buff.reset_ptr(sizeof(int));
+ result = unpack_buffer(buff.buff_ptr, false, from_proc, -1,
dum1a, dum1b, dum1p, dum2, dum2, dum3, entities);
RRA("Failed to unpack buffer in broadcast_entities.");
}
@@ -616,8 +566,7 @@
const bool tags,
const bool store_remote_handles,
const int to_proc,
- std::vector<unsigned char> &buff,
- int &buff_size)
+ Buffer *buff)
{
// pack the buffer with the entity ranges, adjacencies, and tags sections
//
@@ -635,17 +584,13 @@
MBRange::const_iterator rit;
- // get initial buffer ptr
- buff.resize(1);
- unsigned char *buff_ptr = &buff[0];
-
// entities
- result = pack_entities(orig_ents, buff, buff_ptr,
+ result = pack_entities(orig_ents, buff,
store_remote_handles, to_proc, false);
RRA("Packing entities failed.");
// sets
- result = pack_sets(orig_ents, buff, buff_ptr,
+ result = pack_sets(orig_ents, buff,
store_remote_handles, to_proc);
RRA("Packing sets (count) failed.");
@@ -655,11 +600,10 @@
result = get_tag_send_list(orig_ents, all_tags, tag_ranges );
RRA("Failed to get tagged entities.");
result = pack_tags(orig_ents, all_tags, all_tags, tag_ranges,
- buff, buff_ptr, store_remote_handles, to_proc);
+ buff, store_remote_handles, to_proc);
RRA("Packing tags (count) failed.");
}
- buff_size = buff_ptr - &buff[0];
return result;
}
@@ -803,8 +747,7 @@
}
MBErrorCode MBParallelComm::pack_entities(MBRange &entities,
- std::vector<unsigned char> &buff,
- unsigned char *&buff_ptr,
+ Buffer *buff,
const bool store_remote_handles,
const int to_proc,
const bool is_iface,
@@ -822,7 +765,7 @@
// get an estimate of the buffer size & pre-allocate buffer size
unsigned int buff_size = estimate_ents_buffer_size(entities,
store_remote_handles);
- CHECK_BUFF_SPACE(buff, buff_ptr, buff_size);
+ buff->check_space(buff_size);
MBWriteUtilIface *wu;
MBErrorCode result = mbImpl->query_interface(std::string("MBWriteUtilIface"),
@@ -837,11 +780,10 @@
// buff space is at least proc+handle for each entity; use avg of 4 other procs
// to estimate buff size, but check later
- CHECK_BUFF_SPACE(buff, buff_ptr,
- sizeof(int) + (5*sizeof(int) + sizeof(MBEntityHandle))*entities.size());
+ buff->check_space(sizeof(int) + (5*sizeof(int) + sizeof(MBEntityHandle))*entities.size());
// 1. # entities = E
- PACK_INT(buff_ptr, entities.size());
+ PACK_INT(buff->buff_ptr, entities.size());
MBRange::iterator rit;
@@ -868,11 +810,11 @@
RRA("Failed to build sharedhps.");
// now pack them
- CHECK_BUFF_SPACE(buff, buff_ptr, (num_ents+1)*sizeof(int) +
+ buff->check_space((num_ents+1)*sizeof(int) +
num_ents*sizeof(MBEntityHandle));
- PACK_INT(buff_ptr, num_ents);
- PACK_INTS(buff_ptr, tmp_procs, num_ents);
- PACK_EH(buff_ptr, tmp_handles, num_ents);
+ PACK_INT(buff->buff_ptr, num_ents);
+ PACK_INTS(buff->buff_ptr, tmp_procs, num_ents);
+ PACK_EH(buff->buff_ptr, tmp_handles, num_ents);
#ifndef NDEBUG
// check for duplicates in proc list
@@ -891,17 +833,17 @@
if (num_ents) {
buff_size = 2*sizeof(int) + 3*num_ents*sizeof(double);
- CHECK_BUFF_SPACE(buff, buff_ptr, buff_size);
+ buff->check_space(buff_size);
// type, # ents
- PACK_INT(buff_ptr, ((int) MBVERTEX));
- PACK_INT(buff_ptr, ((int) num_ents));
+ PACK_INT(buff->buff_ptr, ((int) MBVERTEX));
+ PACK_INT(buff->buff_ptr, ((int) num_ents));
- result = mbImpl->get_coords(these_ents, (double*)buff_ptr);
+ result = mbImpl->get_coords(these_ents, (double*)buff->buff_ptr);
RRA("Couldn't get vertex coordinates.");
PC(3*num_ents, " doubles");
- buff_ptr += 3 * num_ents * sizeof(double);
+ buff->buff_ptr += 3 * num_ents * sizeof(double);
#ifdef DEBUG_PACKING
std::cerr << "Packed " << these_ents.size() << " ents of type "
@@ -940,7 +882,7 @@
(!eseq || eseq->type() != last_type ||
last_nodes != (int) eseq->nodes_per_element())) {
result = pack_entity_seq(last_nodes, store_remote_handles,
- to_proc, these_ents, entities, buff, buff_ptr);
+ to_proc, these_ents, entities, buff);
RRA("Failed to pack entities from a sequence.");
these_ents.clear();
}
@@ -964,9 +906,10 @@
}
// pack MBMAXTYPE to indicate end of ranges
- CHECK_BUFF_SPACE(buff, buff_ptr, sizeof(int));
- PACK_INT(buff_ptr, ((int)MBMAXTYPE));
+ buff->check_space(sizeof(int));
+ PACK_INT(buff->buff_ptr, ((int)MBMAXTYPE));
+ buff->set_stored_size();
return MB_SUCCESS;
}
@@ -1044,33 +987,32 @@
const int to_proc,
MBRange &these_ents,
MBRange &entities,
- std::vector<unsigned char> &buff,
- unsigned char *&buff_ptr)
+ Buffer *buff)
{
int tmp_space = 3*sizeof(int) + nodes_per_entity*these_ents.size()*sizeof(MBEntityHandle);
- CHECK_BUFF_SPACE(buff, buff_ptr, tmp_space);
+ buff->check_space(tmp_space);
// pack the entity type
- PACK_INT(buff_ptr, ((int)TYPE_FROM_HANDLE(*these_ents.begin())));
+ PACK_INT(buff->buff_ptr, ((int)TYPE_FROM_HANDLE(*these_ents.begin())));
// pack # ents
- PACK_INT(buff_ptr, these_ents.size());
+ PACK_INT(buff->buff_ptr, these_ents.size());
// pack the nodes per entity
- PACK_INT(buff_ptr, nodes_per_entity);
+ PACK_INT(buff->buff_ptr, nodes_per_entity);
// pack the connectivity
const MBEntityHandle *connect;
int num_connect;
std::vector<MBEntityHandle> dum_connect;
- MBEntityHandle *start_vec = (MBEntityHandle*)buff_ptr;
+ MBEntityHandle *start_vec = (MBEntityHandle*)buff->buff_ptr;
MBErrorCode result = MB_SUCCESS;
for (MBRange::const_iterator rit = these_ents.begin(); rit != these_ents.end(); rit++) {
result = mbImpl->get_connectivity(*rit, connect, num_connect, false,
&dum_connect);
RRA("Failed to get connectivity.");
assert(num_connect == nodes_per_entity);
- PACK_EH(buff_ptr, connect, num_connect);
+ PACK_EH(buff->buff_ptr, connect, num_connect);
}
// substitute destination handles
@@ -1539,27 +1481,26 @@
int mesg_tag,
int from_proc, bool sent)
{
- std::cout << procConfig.proc_rank();
- if (sent) std::cout << " sent";
- else std::cout << " received";
- std::cout << " message type " << mesg_tag
+ std::cerr << procConfig.proc_rank();
+ if (sent) std::cerr << " sent";
+ else std::cerr << " received";
+ std::cerr << " message type " << mesg_tag
<< " to/from proc " << from_proc << "; contents:" << std::endl;
- int msg_length;
+ int msg_length, num_ents;
unsigned char *orig_ptr = buff_ptr;
UNPACK_INT(buff_ptr, msg_length);
- std::cout << msg_length << " bytes..." << std::endl;
+ std::cerr << msg_length << " bytes..." << std::endl;
- if (MB_MESG_ENTS == mesg_tag) {
+ if (MB_MESG_ENTS_SIZE == mesg_tag || MB_MESG_ENTS_LARGE == mesg_tag) {
// 1. # entities = E
- int num_ents;
int i, j, k;
std::vector<int> ps;
std::vector<MBEntityHandle> hs;
UNPACK_INT(buff_ptr, num_ents);
- std::cout << num_ents << " entities..." << std::endl;
+ std::cerr << num_ents << " entities..." << std::endl;
// save place where remote handle info starts, then scan forward to ents
for (i = 0; i < num_ents; i++) {
@@ -1567,18 +1508,19 @@
if (0 > j) return MB_FAILURE;
ps.resize(j);
hs.resize(j);
- std::cout << "Entity " << i << ", # procs = " << j << std::endl;
+ std::cerr << "Entity " << i << ", # procs = " << j << std::endl;
UNPACK_INTS(buff_ptr, &ps[0], j);
UNPACK_EH(buff_ptr, &hs[0], j);
- std::cout << " Procs: ";
- for (k = 0; k < j; k++) std::cout << ps[k] << " ";
- std::cout << std::endl;
- std::cout << " Handles: ";
- for (k = 0; k < j; k++) std::cout << hs[k] << " ";
- std::cout << std::endl;
+ std::cerr << " Procs: ";
+ for (k = 0; k < j; k++) std::cerr << ps[k] << " ";
+ std::cerr << std::endl;
+ std::cerr << " Handles: ";
+ for (k = 0; k < j; k++) std::cerr << hs[k] << " ";
+ std::cerr << std::endl;
if (buff_ptr-orig_ptr > msg_length) {
- std::cout << "End of buffer..." << std::endl;
+ std::cerr << "End of buffer..." << std::endl;
+ std::cerr.flush();
return MB_FAILURE;
}
}
@@ -1600,10 +1542,14 @@
UNPACK_INT(buff_ptr, verts_per_entity);
}
- std::cout << "Type: " << MBCN::EntityTypeName(this_type)
+ std::cerr << "Type: " << MBCN::EntityTypeName(this_type)
<< "; num_ents = " << num_ents2;
- if (MBVERTEX != this_type) std::cout << "; verts_per_ent = " << verts_per_entity;
- std::cout << std::endl;
+ if (MBVERTEX != this_type) std::cerr << "; verts_per_ent = " << verts_per_entity;
+ std::cerr << std::endl;
+ if (num_ents2 < 0 || num_ents2 > msg_length) {
+ std::cerr << "Wrong number of entities, returning." << std::endl;
+ return MB_FAILURE;
+ }
for (int e = 0; e < num_ents2; e++) {
// check for existing entity, otherwise make new one
@@ -1613,7 +1559,7 @@
if (MBVERTEX == this_type) {
coords = (double*) buff_ptr;
buff_ptr += 3*sizeof(double);
- std::cout << "xyz = " << coords[0] << ", " << coords[1] << ", "
+ std::cerr << "xyz = " << coords[0] << ", " << coords[1] << ", "
<< coords[2] << std::endl;
}
else {
@@ -1621,53 +1567,59 @@
buff_ptr += verts_per_entity * sizeof(MBEntityHandle);
// update connectivity to local handles
- std::cout << "Connectivity: ";
- for (k = 0; k < verts_per_entity; k++) std::cout << connect[k] << " ";
- std::cout << std::endl;
+ std::cerr << "Connectivity: ";
+ for (k = 0; k < verts_per_entity; k++) std::cerr << connect[k] << " ";
+ std::cerr << std::endl;
}
if (buff_ptr-orig_ptr > msg_length) {
- std::cout << "End of buffer..." << std::endl;
+ std::cerr << "End of buffer..." << std::endl;
+ std::cerr.flush();
return MB_FAILURE;
}
}
}
}
- else if (MB_MESG_REMOTE_HANDLES) {
- int num_bytes;
- UNPACK_INT(buff_ptr, num_bytes);
- std::cout << num_bytes << " bytes..." << std::endl;
- int num_ents;
+ else if (MB_MESG_REMOTEH_SIZE == mesg_tag || MB_MESG_REMOTEH_LARGE == mesg_tag) {
UNPACK_INT(buff_ptr, num_ents);
+ std::cerr << num_ents << " entities..." << std::endl;
+ if (0 > num_ents || num_ents > msg_length) {
+ std::cerr << "Wrong number of entities, returning." << std::endl;
+ return MB_FAILURE;
+ }
std::vector<MBEntityHandle> L1hloc(num_ents), L1hrem(num_ents);
std::vector<int> L1p(num_ents);
UNPACK_INTS(buff_ptr, &L1p[0], num_ents);
UNPACK_EH(buff_ptr, &L1hrem[0], num_ents);
UNPACK_EH(buff_ptr, &L1hloc[0], num_ents);
- std::cout << num_ents << " Entity pairs; hremote/hlocal/proc: " << std::endl;
+ std::cerr << num_ents << " Entity pairs; hremote/hlocal/proc: " << std::endl;
for (int i = 0; i < num_ents; i++) {
MBEntityType etype = TYPE_FROM_HANDLE(L1hloc[i]);
- std::cout << MBCN::EntityTypeName(etype) << ID_FROM_HANDLE(L1hrem[i]) << ", "
+ std::cerr << MBCN::EntityTypeName(etype) << ID_FROM_HANDLE(L1hrem[i]) << ", "
<< MBCN::EntityTypeName(etype) << ID_FROM_HANDLE(L1hloc[i]) << ", "
<< L1p[i] << std::endl;
}
if (buff_ptr-orig_ptr > msg_length) {
- std::cout << "End of buffer..." << std::endl;
+ std::cerr << "End of buffer..." << std::endl;
+ std::cerr.flush();
return MB_FAILURE;
}
}
- else if (MB_MESG_TAGS) {
- assert(false);
- return MB_FAILURE;
+ else if (mesg_tag == MB_MESG_TAGS_SIZE || mesg_tag == MB_MESG_TAGS_LARGE) {
+ std::cerr << "Printed as ints: " << std::endl;
+ for (int i = 0; i < msg_length; i+= sizeof(int))
+ std::cerr << *((int*)buff_ptr[i]) << std::endl;
}
else {
assert(false);
return MB_FAILURE;
}
+ std::cerr.flush();
+
return MB_SUCCESS;
}
@@ -2096,8 +2048,7 @@
}
MBErrorCode MBParallelComm::pack_sets(MBRange &entities,
- std::vector<unsigned char> &buff,
- unsigned char *&buff_ptr,
+ Buffer *buff,
const bool store_remote_handles,
const int to_proc)
{
@@ -2119,10 +2070,10 @@
MBRange all_sets = entities.subset_by_type(MBENTITYSET);
int buff_size = estimate_sets_buffer_size(all_sets, store_remote_handles);
- CHECK_BUFF_SPACE(buff, buff_ptr, buff_size);
+ buff->check_space(buff_size);
// number of sets
- PACK_INT(buff_ptr, all_sets.size());
+ PACK_INT(buff->buff_ptr, all_sets.size());
// options for all sets
std::vector<unsigned int> options(all_sets.size());
@@ -2133,8 +2084,8 @@
result = mbImpl->get_meshset_options(*rit, options[i]);
RRA("Failed to get meshset options.");
}
- CHECK_BUFF_SPACE(buff, buff_ptr, all_sets.size()*sizeof(unsigned int));
- PACK_VOID(buff_ptr, &options[0], all_sets.size()*sizeof(unsigned int));
+ buff->check_space(all_sets.size()*sizeof(unsigned int));
+ PACK_VOID(buff->buff_ptr, &options[0], all_sets.size()*sizeof(unsigned int));
// vectors/ranges
for (rit = all_sets.begin(), i = 0; rit != all_sets.end(); rit++, i++) {
@@ -2145,33 +2096,32 @@
RRA("Failed to get set entities.");
buff_size = RANGE_SIZE(set_range);
- CHECK_BUFF_SPACE(buff, buff_ptr, buff_size);
- PACK_RANGE(buff_ptr, set_range);
+ buff->check_space(buff_size);
+ PACK_RANGE(buff->buff_ptr, set_range);
}
else if (options[i] & MESHSET_ORDERED) {
members.clear();
result = mbImpl->get_entities_by_handle(*rit, members);
RRA("Failed to get entities in ordered set.");
- CHECK_BUFF_SPACE(buff, buff_ptr,
- members.size()*sizeof(MBEntityHandle)+sizeof(int));
- PACK_INT(buff_ptr, members.size());
- PACK_EH(buff_ptr, &members[0], members.size());
+ buff->check_space(members.size()*sizeof(MBEntityHandle)+sizeof(int));
+ PACK_INT(buff->buff_ptr, members.size());
+ PACK_EH(buff->buff_ptr, &members[0], members.size());
}
}
// pack numbers of parents/children
unsigned int tot_pch = 0;
int num_pch;
- CHECK_BUFF_SPACE(buff, buff_ptr, 2*all_sets.size()*sizeof(int));
+ buff->check_space(2*all_sets.size()*sizeof(int));
for (rit = all_sets.begin(), i = 0; rit != all_sets.end(); rit++, i++) {
// pack parents
result = mbImpl->num_parent_meshsets(*rit, &num_pch);
RRA("Failed to get num parents.");
- PACK_INT(buff_ptr, num_pch);
+ PACK_INT(buff->buff_ptr, num_pch);
tot_pch += num_pch;
result = mbImpl->num_child_meshsets(*rit, &num_pch);
RRA("Failed to get num children.");
- PACK_INT(buff_ptr, num_pch);
+ PACK_INT(buff->buff_ptr, num_pch);
tot_pch += num_pch;
}
@@ -2203,21 +2153,23 @@
ID_FROM_HANDLE(members[__j]) < (int)entities.size()) ||
TYPE_FROM_HANDLE(members[__j]) == MBENTITYSET);
#endif
- CHECK_BUFF_SPACE(buff, buff_ptr, members.size()*sizeof(MBEntityHandle));
- PACK_EH(buff_ptr, &members[0], members.size());
+ buff->check_space(members.size()*sizeof(MBEntityHandle));
+ PACK_EH(buff->buff_ptr, &members[0], members.size());
}
// pack the handles
if (store_remote_handles && !all_sets.empty()) {
buff_size = RANGE_SIZE(all_sets);
- CHECK_BUFF_SPACE(buff, buff_ptr, buff_size);
- PACK_RANGE(buff_ptr, all_sets);
+ buff->check_space(buff_size);
+ PACK_RANGE(buff->buff_ptr, all_sets);
}
#ifdef DEBUG_PACKING
std::cerr << std::endl << "Done packing sets." << std::endl;
#endif
+ buff->set_stored_size();
+
return MB_SUCCESS;
}
@@ -2356,8 +2308,7 @@
const std::vector<MBTag> &src_tags,
const std::vector<MBTag> &dst_tags,
const std::vector<MBRange> &tag_ranges,
- std::vector<unsigned char> &buff,
- unsigned char *&buff_ptr,
+ Buffer *buff,
const bool store_remote_handles,
const int to_proc)
{
@@ -2379,14 +2330,14 @@
// number of tags
count += sizeof(int);
- CHECK_BUFF_SPACE(buff, buff_ptr, count);
+ buff->check_space(count);
- PACK_INT(buff_ptr, src_tags.size());
+ PACK_INT(buff->buff_ptr, src_tags.size());
for (tag_it = src_tags.begin(), dst_it = dst_tags.begin(), rit = tag_ranges.begin();
tag_it != src_tags.end(); tag_it++, dst_it++, rit++) {
- result = pack_tag( *tag_it, *dst_it, *rit, entities, buff, buff_ptr,
+ result = pack_tag( *tag_it, *dst_it, *rit, entities, buff,
store_remote_handles, to_proc );
if (MB_SUCCESS != result)
return result;
@@ -2396,6 +2347,8 @@
std::cerr << std::endl << "Done packing tags." << std::endl;
#endif
+ buff->set_stored_size();
+
return MB_SUCCESS;
}
@@ -2453,8 +2406,7 @@
MBTag dst_tag,
const MBRange &tagged_entities,
const MBRange &whole_range,
- std::vector<unsigned char> &buff,
- unsigned char *&buff_ptr,
+ Buffer *buff,
const bool store_remote_handles,
const int to_proc )
{
@@ -2483,26 +2435,26 @@
}
// size, type, data type
- CHECK_BUFF_SPACE(buff, buff_ptr, 3*sizeof(int));
- PACK_INT(buff_ptr, tinfo->get_size());
+ buff->check_space(3*sizeof(int));
+ PACK_INT(buff->buff_ptr, tinfo->get_size());
MBTagType this_type;
result = mbImpl->tag_get_type(dst_tag, this_type);
- PACK_INT(buff_ptr, (int)this_type);
- PACK_INT(buff_ptr, (int)(tinfo->get_data_type()));
+ PACK_INT(buff->buff_ptr, (int)this_type);
+ PACK_INT(buff->buff_ptr, (int)(tinfo->get_data_type()));
// default value
if (NULL == tinfo->default_value()) {
- CHECK_BUFF_SPACE(buff, buff_ptr, sizeof(int));
- PACK_INT(buff_ptr, 0);
+ buff->check_space(sizeof(int));
+ PACK_INT(buff->buff_ptr, 0);
}
else {
- CHECK_BUFF_SPACE(buff, buff_ptr, tinfo->default_value_size());
- PACK_BYTES(buff_ptr, tinfo->default_value(), tinfo->default_value_size());
+ buff->check_space(tinfo->default_value_size());
+ PACK_BYTES(buff->buff_ptr, tinfo->default_value(), tinfo->default_value_size());
}
// name
- CHECK_BUFF_SPACE(buff, buff_ptr, tinfo->get_name().size());
- PACK_BYTES(buff_ptr, dst_tinfo->get_name().c_str(), dst_tinfo->get_name().size());
+ buff->check_space(tinfo->get_name().size());
+ PACK_BYTES(buff->buff_ptr, dst_tinfo->get_name().c_str(), dst_tinfo->get_name().size());
#ifdef DEBUG_PACKING
std::cerr << "Packing tag \"" << tinfo->get_name() << "\"";
@@ -2511,10 +2463,10 @@
std::cerr << std::endl;
#endif
// pack entities
- CHECK_BUFF_SPACE(buff, buff_ptr, tagged_entities.size()*sizeof(MBEntityHandle)+sizeof(int));
- PACK_INT(buff_ptr, tagged_entities.size());
+ buff->check_space(tagged_entities.size()*sizeof(MBEntityHandle)+sizeof(int));
+ PACK_INT(buff->buff_ptr, tagged_entities.size());
result = get_remote_handles(store_remote_handles,
- tagged_entities, (MBEntityHandle*)buff_ptr, to_proc,
+ tagged_entities, (MBEntityHandle*)buff->buff_ptr, to_proc,
whole_range);
#ifdef DEBUG_PACKING
if (MB_SUCCESS != result) {
@@ -2525,7 +2477,7 @@
RRA("Trouble getting remote handles for tagged entities.");
#endif
- buff_ptr += tagged_entities.size() * sizeof(MBEntityHandle);
+ buff->buff_ptr += tagged_entities.size() * sizeof(MBEntityHandle);
const size_t num_ent = tagged_entities.size();
if (tinfo->get_size() == MB_VARIABLE_LENGTH) {
@@ -2534,18 +2486,18 @@
result = mbImpl->tag_get_data(src_tag, tagged_entities, &var_len_values[0],
&var_len_sizes[0] );
RRA("Failed to get variable-length tag data in pack_tags.");
- CHECK_BUFF_SPACE(buff, buff_ptr, num_ent*sizeof(int));
- PACK_INTS(buff_ptr, &var_len_sizes[0], num_ent);
+ buff->check_space(num_ent*sizeof(int));
+ PACK_INTS(buff->buff_ptr, &var_len_sizes[0], num_ent);
for (unsigned int i = 0; i < num_ent; ++i) {
- CHECK_BUFF_SPACE(buff, buff_ptr, var_len_sizes[i]);
- PACK_VOID(buff_ptr, var_len_values[i], var_len_sizes[i]);
+ buff->check_space(var_len_sizes[i]);
+ PACK_VOID(buff->buff_ptr, var_len_values[i], var_len_sizes[i]);
}
}
else {
- CHECK_BUFF_SPACE(buff, buff_ptr, num_ent * tinfo->get_size());
- result = mbImpl->tag_get_data(src_tag, tagged_entities, buff_ptr);
+ buff->check_space(num_ent * tinfo->get_size());
+ result = mbImpl->tag_get_data(src_tag, tagged_entities, buff->buff_ptr);
RRA("Failed to get tag data in pack_tags.");
- buff_ptr += num_ent * tinfo->get_size();
+ buff->buff_ptr += num_ent * tinfo->get_size();
PC(num_ent*tinfo->get_size(), " void");
}
@@ -3764,22 +3716,31 @@
#endif
#ifdef DEBUG_COMM
- std::cout << "Entering exchange_ghost_cells with num_layers = "
- << num_layers << std::endl;
+// std::ostringstream pfile("p");
+// pfile << "p" << procConfig.proc_rank() << ".txt";
+// std::cerr.open(pfile.str().c_str(), std::ios_base::trunc);
+ std::cerr << "Entering exchange_ghost_cells with num_layers = "
+ << num_layers << std::endl; std::cerr.flush();
#endif
+#ifdef DEBUG_MSGS
+ msgs.clear();
+ msgs.reserve(MAX_SHARING_PROCS);
+#endif
// if we're only finding out about existing ents, we have to be storing
// remote handles too
assert(num_layers > 0 || store_remote_handles);
const bool is_iface = !num_layers;
-
+
// get the b-dimensional interface(s) with with_proc, where b = bridge_dim
int success;
- unsigned char *buff_ptr;
MBErrorCode result = MB_SUCCESS;
+ int incoming1 = 0, incoming2 = 0;
+ reset_all_buffers();
+
// when this function is called, buffProcs should already have any
// communicating procs
@@ -3787,23 +3748,24 @@
// post ghost irecv's for ghost entities from all communicating procs
//===========================================
#ifdef DEBUG_MPE
- MPE_Log_event(ENTITIES_START, procConfig.proc_rank(), "Starting entity exchange.");
+ MPE_Log_event(ENTITIES_START, procConfig.proc_rank(), "Starting entity exchange.");
#endif
// index reqs the same as buffer/sharing procs indices
- std::vector<MPI_Request> recv_reqs(buffProcs.size(), MPI_REQUEST_NULL);
+ std::vector<MPI_Request> recv_ent_reqs(2*buffProcs.size(), MPI_REQUEST_NULL),
+ recv_remoteh_reqs(2*buffProcs.size(), MPI_REQUEST_NULL);
std::vector<unsigned int>::iterator proc_it;
- int ind;
- std::fill(sendReqs, sendReqs+2*buffProcs.size(), MPI_REQUEST_NULL);
+ int ind, p;
+ sendReqs.resize(2*buffProcs.size(), MPI_REQUEST_NULL);
for (ind = 0, proc_it = buffProcs.begin();
proc_it != buffProcs.end(); proc_it++, ind++) {
-#ifdef DEBUG_COMM
- std::cout << "Posting Irecv from " << buffProcs[ind]
- << " for ghost entities." << std::endl;
-#endif
- success = MPI_Irecv(&ghostRBuffs[ind][0], ghostRBuffs[ind].size(),
+ incoming1++;
+ PRINT_DEBUG_IRECV(procConfig.proc_rank(), buffProcs[ind],
+ remoteOwnedBuffs[ind]->mem_ptr, INITIAL_BUFF_SIZE,
+ MB_MESG_ENTS_SIZE, incoming1);
+ success = MPI_Irecv(remoteOwnedBuffs[ind]->mem_ptr, INITIAL_BUFF_SIZE,
MPI_UNSIGNED_CHAR, buffProcs[ind],
- MB_MESG_ENTS, procConfig.proc_comm(),
- &recv_reqs[ind]);
+ MB_MESG_ENTS_SIZE, procConfig.proc_comm(),
+ &recv_ent_reqs[2*ind]);
if (success != MPI_SUCCESS) {
result = MB_FAILURE;
RRA("Failed to post irecv in ghost exchange.");
@@ -3816,6 +3778,7 @@
MBRange sent_ents[MAX_SHARING_PROCS], allsent, tmp_range;
std::vector<std::set<unsigned int> > entprocs(allsent.size());
+ int dum_ack_buff;
result = get_sent_ents(is_iface, bridge_dim, ghost_dim, num_layers,
sent_ents, allsent, entprocs);
RRA("get_sent_ents failed.");
@@ -3823,107 +3786,135 @@
//===========================================
// pack and send ents from this proc to others
//===========================================
- for (ind = 0, proc_it = buffProcs.begin();
- proc_it != buffProcs.end(); proc_it++, ind++) {
+ for (p = 0, proc_it = buffProcs.begin();
+ proc_it != buffProcs.end(); proc_it++, p++) {
// reserve space on front for size and for initial buff size
- INIT_BUFFER(ownerSBuffs[ind], buff_ptr);
+ localOwnedBuffs[p]->reset_buffer(sizeof(int));
// entities
- result = pack_entities(sent_ents[ind], ownerSBuffs[ind], buff_ptr,
- store_remote_handles, buffProcs[ind], is_iface,
+ result = pack_entities(sent_ents[p], localOwnedBuffs[p],
+ store_remote_handles, buffProcs[p], is_iface,
&entprocs, &allsent);
RRA("Packing entities failed.");
#ifdef DEBUG_MSGS
- result = print_buffer(&ownerSBuffs[ind][0], MB_MESG_ENTS, *proc_it, true);
+ msgs.resize(msgs.size()+1);
+ msgs.back() = new Buffer(*localOwnedBuffs[p]);
+ //result = print_buffer(&ownerSBuffs[ind][0], MB_MESG_ENTS_SIZE, *proc_it, true);
#endif
-
- // send the buffer (buffer size saved in send_buffer)
- result = send_buffer(*proc_it, &ownerSBuffs[ind][0],
- buff_ptr-&ownerSBuffs[ind][0], MB_MESG_ENTS,
- sendReqs[ind], sendReqs[ind+buffProcs.size()]);
+
+ // send the buffer (size stored in front in send_buffer)
+ result = send_buffer(*proc_it, localOwnedBuffs[p],
+ MB_MESG_ENTS_SIZE, sendReqs[2*p],
+ recv_ent_reqs[2*p+1], &dum_ack_buff,
+ incoming1,
+ MB_MESG_REMOTEH_SIZE,
+ (!is_iface && store_remote_handles ?
+ localOwnedBuffs[p] : NULL),
+ &recv_remoteh_reqs[2*p], &incoming2);
RRA("Failed to Isend in ghost exchange.");
+ }
-// if (1 == num_layers)
-// print_buffer(&ownerSBuffs[ind][0], MB_MESG_ENTS, *proc_it, true);
- }
//===========================================
// receive/unpack new entities
//===========================================
// number of incoming messages for ghosts is the number of procs we
// communicate with; for iface, it's the number of those with lower rank
- int num_incoming = buffProcs.size();
- std::vector<MPI_Status> status(MAX_SHARING_PROCS);
- std::vector<std::vector<MBEntityHandle> > recd_ents(num_incoming);
+ MPI_Status status;
+ std::vector<std::vector<MBEntityHandle> > recd_ents(buffProcs.size());
std::vector<std::vector<MBEntityHandle> > L1hloc(buffProcs.size()), L1hrem(buffProcs.size());
std::vector<std::vector<int> > L1p(buffProcs.size());
std::vector<MBEntityHandle> L2hloc, L2hrem;
std::vector<unsigned int> L2p;
MBRange new_ents;
- while (num_incoming) {
- // wait for all recvs of ghost ents before proceeding,
+ while (incoming1) {
+ // wait for all recvs of ghost ents before proceeding to sending remote handles,
// b/c some procs may have sent to a 3rd proc ents owned by me;
- success = MPI_Waitany(buffProcs.size(), &recv_reqs[0], &ind, &status[0]);
+ PRINT_DEBUG_WAITANY(recv_ent_reqs, MB_MESG_ENTS_SIZE, procConfig.proc_rank());
+
+ success = MPI_Waitany(2*buffProcs.size(), &recv_ent_reqs[0], &ind, &status);
if (MPI_SUCCESS != success) {
result = MB_FAILURE;
RRA("Failed in waitany in ghost exchange.");
}
-#ifdef DEBUG_COMM
- {
- int this_count;
- success = MPI_Get_count(&status[0], MPI_UNSIGNED_CHAR, &this_count);
- if (MPI_SUCCESS != success) this_count = -1;
-
- std::cerr << "Received from " << status[0].MPI_SOURCE
- << ", count = " << this_count << ", tag = " << status[0].MPI_TAG;
- if (MB_MESG_ENTS+1 == status[0].MPI_TAG) std::cerr << " (second)";
- std::cerr << std::endl;
- }
-#endif
+
+ PRINT_DEBUG_RECD(status);
// ok, received something; decrement incoming counter
- num_incoming--;
+ incoming1--;
+ bool done = false;
- bool done = false;
-
- result = recv_buffer(MB_MESG_ENTS, status[0],
- ghostRBuffs[ind], recv_reqs[ind], done);
- RRA("Failed to receive entities.");
-
+ // In case ind is for ack, we need index of one before it
+ unsigned int base_ind = 2*(ind/2);
+ result = recv_buffer(MB_MESG_ENTS_SIZE,
+ status,
+ remoteOwnedBuffs[ind/2],
+ recv_ent_reqs[ind], recv_ent_reqs[ind+1],
+ incoming1,
+ localOwnedBuffs[ind/2], sendReqs[base_ind], sendReqs[base_ind+1],
+ done,
+ (!is_iface && store_remote_handles ?
+ localOwnedBuffs[ind/2] : NULL),
+ MB_MESG_REMOTEH_SIZE,
+ &recv_remoteh_reqs[base_ind], &incoming2);
+ RRA("Failed to receive buffer.");
+
if (done) {
#ifdef DEBUG_MSGS
- print_buffer(&ghostRBuffs[ind][0], MB_MESG_ENTS, buffProcs[ind], false);
-#endif
- unsigned char *buff_ptr = &ghostRBuffs[ind][sizeof(int)];
- result = unpack_entities(buff_ptr,
- store_remote_handles, ind, is_iface,
- L1hloc, L1hrem, L1p, L2hloc, L2hrem, L2p, new_ents);
+ msgs.resize(msgs.size()+1);
+ msgs.back() = new Buffer(*remoteOwnedBuffs[ind/2]);
+ //print_buffer(&ghostRBuffs[ind/2][0], MB_MESG_ENTS_SIZE, buffProcs[ind/2], false);
+#endif
+
+ // message completely received - process buffer that was sent
+ remoteOwnedBuffs[ind/2]->reset_ptr(sizeof(int));
+ result = unpack_entities(remoteOwnedBuffs[ind/2]->buff_ptr,
+ store_remote_handles, ind/2, is_iface,
+ L1hloc, L1hrem, L1p, L2hloc, L2hrem, L2p, new_ents);
if (MB_SUCCESS != result) {
std::cout << "Failed to unpack entities. Buffer contents:" << std::endl;
- print_buffer(&ghostRBuffs[ind][0], MB_MESG_ENTS, buffProcs[ind], false);
+ print_buffer(remoteOwnedBuffs[ind/2]->mem_ptr, MB_MESG_ENTS_SIZE, buffProcs[ind/2], false);
return result;
}
- if (recv_reqs.size() != buffProcs.size()) {
- recv_reqs.resize(buffProcs.size(), MPI_REQUEST_NULL);
+ if (recv_ent_reqs.size() != 2*buffProcs.size()) {
+ // post irecv's for remote handles from new proc; shouldn't be iface,
+ // since we know about all procs we share with
+ assert(!is_iface);
+ recv_remoteh_reqs.resize(2*buffProcs.size(), MPI_REQUEST_NULL);
+ for (unsigned int i = recv_ent_reqs.size(); i < 2*buffProcs.size(); i+=2) {
+ localOwnedBuffs[i/2]->reset_buffer();
+ incoming2++;
+ PRINT_DEBUG_IRECV(procConfig.proc_rank(), buffProcs[i/2],
+ localOwnedBuffs[i/2]->mem_ptr, INITIAL_BUFF_SIZE,
+ MB_MESG_REMOTEH_SIZE, incoming2);
+ success = MPI_Irecv(localOwnedBuffs[i/2]->mem_ptr, INITIAL_BUFF_SIZE,
+ MPI_UNSIGNED_CHAR, buffProcs[i/2],
+ MB_MESG_REMOTEH_SIZE, procConfig.proc_comm(),
+ &recv_remoteh_reqs[i]);
+ if (success != MPI_SUCCESS) {
+ result = MB_FAILURE;
+ RRA("Failed to post irecv for remote handles in ghost exchange.");
+ }
+ }
+ recv_ent_reqs.resize(2*buffProcs.size(), MPI_REQUEST_NULL);
+ sendReqs.resize(2*buffProcs.size(), MPI_REQUEST_NULL);
}
}
- else {
- num_incoming++;
- continue;
- }
}
-
+
// add requests for any new addl procs
- if (recv_reqs.size() != buffProcs.size()) {
- recv_reqs.resize(buffProcs.size(), MPI_REQUEST_NULL);
+ if (recv_ent_reqs.size() != 2*buffProcs.size()) {
+ // shouldn't get here...
+ result = MB_FAILURE;
+ RRA("Requests length doesn't match proc count in ghost exchange.");
}
#ifdef DEBUG_MPE
- MPE_Log_event(ENTITIES_END, procConfig.proc_rank(), "Ending entity exchange.");
+ MPE_Log_event(ENTITIES_END, procConfig.proc_rank(), "Ending entity exchange.");
#endif
if (is_iface) {
@@ -3948,17 +3939,18 @@
MPE_Log_event(IFACE_END, procConfig.proc_rank(), "Ending interface exchange.");
#endif
#ifdef DEBUG_COMM
- std::cout << "Exiting exchange_ghost_cells" << std::endl;
+ std::cerr << "Exiting exchange_ghost_cells" << std::endl; std::cerr.flush();
#endif
- //===========================================
- // wait if requested
- //===========================================
+ //===========================================
+ // wait if requested
+ //===========================================
if (wait_all) {
-#ifdef DEBUG_COMM
+#ifdef DEBUG_BARRIER
success = MPI_Barrier(procConfig.proc_comm());
#else
- success = MPI_Waitall(buffProcs.size(), &recv_reqs[0], &status[0]);
+ success = MPI_Waitall(2*buffProcs.size(), &recv_ent_reqs[0], &status);
+ success = MPI_Waitall(2*buffProcs.size(), &sendReqs[0], &status);
#endif
if (MPI_SUCCESS != success) {
result = MB_FAILURE;
@@ -3967,128 +3959,91 @@
}
return MB_SUCCESS;
}
-
+
//===========================================
- // post recvs for remote handles of my sent ents
- //===========================================
-#ifdef DEBUG_MPE
- MPE_Log_event(RHANDLES_START, procConfig.proc_rank(), "Starting remote handles.");
-#endif
- for (ind = 0, proc_it = buffProcs.begin();
- proc_it != buffProcs.end(); proc_it++, ind++) {
- // skip if iface layer and lower-rank proc
-#ifdef DEBUG_COMM
- std::cout << "Posting Irecv from " << buffProcs[ind]
- << " for remote handles." << std::endl;
-#endif
- success = MPI_Irecv(&ghostRBuffs[ind][0], ghostRBuffs[ind].size(),
- MPI_UNSIGNED_CHAR, buffProcs[ind],
- MB_MESG_REMOTE_HANDLES, procConfig.proc_comm(),
- &recv_reqs[ind]);
- if (success != MPI_SUCCESS) {
- result = MB_FAILURE;
- RRA("Failed to post irecv in ghost exchange.");
- }
- }
-
- //===========================================
// send local handles for new ghosts to owner, then add
// those to ghost list for that owner
//===========================================
- for (ind = 0, proc_it = buffProcs.begin();
- proc_it != buffProcs.end(); proc_it++, ind++) {
+ for (p = 0, proc_it = buffProcs.begin();
+ proc_it != buffProcs.end(); proc_it++, p++) {
// reserve space on front for size and for initial buff size
- INIT_BUFFER(ownerSBuffs[ind], buff_ptr);
+ remoteOwnedBuffs[p]->reset_buffer(sizeof(int));
- result = pack_remote_handles(L1hloc[ind], L1hrem[ind], L1p[ind], *proc_it,
- ownerSBuffs[ind], buff_ptr);
+ result = pack_remote_handles(L1hloc[p], L1hrem[p], L1p[p], *proc_it,
+ remoteOwnedBuffs[p]);
RRA("Failed to pack remote handles.");
-
+ remoteOwnedBuffs[p]->set_stored_size();
+
#ifdef DEBUG_MSGS
- print_buffer(&ownerSBuffs[ind][0], MB_MESG_REMOTE_HANDLES, buffProcs[ind], true);
+ msgs.resize(msgs.size()+1);
+ msgs.back() = new Buffer(*remoteOwnedBuffs[p]);
+ //print_buffer(&ownerSBuffs[ind][0], MB_MESG_REMOTEH_SIZE, buffProcs[ind], true);
#endif
- result = send_buffer(buffProcs[ind], &ownerSBuffs[ind][0],
- buff_ptr - &ownerSBuffs[ind][0],
- MB_MESG_REMOTE_HANDLES,
- sendReqs[ind], sendReqs[ind+buffProcs.size()]);
+ result = send_buffer(buffProcs[p], remoteOwnedBuffs[p],
+ MB_MESG_REMOTEH_SIZE,
+ sendReqs[2*p], recv_remoteh_reqs[2*p+1],
+ &dum_ack_buff, incoming2);
RRA("Failed to send remote handles.");
}
//===========================================
// process remote handles of my ghosteds
//===========================================
- num_incoming = buffProcs.size();
- while (num_incoming) {
- success = MPI_Waitany(buffProcs.size(), &recv_reqs[0], &ind, &status[0]);
+ while (incoming2) {
+ PRINT_DEBUG_WAITANY(recv_remoteh_reqs, MB_MESG_REMOTEH_SIZE, procConfig.proc_rank());
+ success = MPI_Waitany(2*buffProcs.size(), &recv_remoteh_reqs[0], &ind, &status);
if (MPI_SUCCESS != success) {
result = MB_FAILURE;
RRA("Failed in waitany in ghost exchange.");
}
// ok, received something; decrement incoming counter
- num_incoming--;
+ incoming2--;
+
+ PRINT_DEBUG_RECD(status);
-#ifdef DEBUG_COMM
- {
- int this_count;
- success = MPI_Get_count(&status[0], MPI_UNSIGNED_CHAR, &this_count);
- if (MPI_SUCCESS != success) this_count = -1;
-
- std::cerr << "Received from " << status[0].MPI_SOURCE
- << ", count = " << this_count << ", tag = " << status[0].MPI_TAG;
- if (MB_MESG_REMOTE_HANDLES_SECOND == status[0].MPI_TAG)
- std::cerr << " (second)";
- std::cerr << std::endl;
- }
-#endif
-
- bool done;
- result = recv_buffer(MB_MESG_REMOTE_HANDLES, status[0],
- ghostRBuffs[ind], recv_reqs[ind], done);
- RRA("Failed to resize recv buffer.");
+ bool done = false;
+ unsigned int base_ind = 2*(ind/2);
+ result = recv_buffer(MB_MESG_REMOTEH_SIZE, status,
+ localOwnedBuffs[ind/2],
+ recv_remoteh_reqs[ind], recv_remoteh_reqs[ind+1], incoming2,
+ remoteOwnedBuffs[ind/2],
+ sendReqs[base_ind], sendReqs[base_ind+1],
+ done);
+ RRA("Failed to receive remote handles.");
if (done) {
// incoming remote handles
#ifdef DEBUG_MSGS
- print_buffer(&ghostRBuffs[ind][0], MB_MESG_REMOTE_HANDLES, buffProcs[ind], false);
+ msgs.resize(msgs.size()+1);
+ msgs.back() = new Buffer(*localOwnedBuffs[ind]);
+ //print_buffer(&remotehRBuffs[ind/2][0], MB_MESG_REMOTEH_SIZE, buffProcs[ind/2], false);
#endif
- buff_ptr = &ghostRBuffs[ind][sizeof(int)];
- result = unpack_remote_handles(buffProcs[ind], buff_ptr,
- L2hloc, L2hrem, L2p);
+ localOwnedBuffs[ind/2]->reset_ptr(sizeof(int));
+ result = unpack_remote_handles(buffProcs[ind/2],
+ localOwnedBuffs[ind/2]->buff_ptr,
+ L2hloc, L2hrem, L2p);
RRA("Failed to unpack remote handles.");
}
- else {
- num_incoming++;
- continue;
- }
}
#ifdef DEBUG_MPE
- MPE_Log_event(RHANDLES_END, procConfig.proc_rank(), "Ending remote handles.");
+ MPE_Log_event(RHANDLES_END, procConfig.proc_rank(), "Ending remote handles.");
#endif
#ifdef DEBUG_MPE
- MPE_Log_event(GHOST_END, procConfig.proc_rank(),
- "Ending ghost exchange (still doing checks).");
+ MPE_Log_event(GHOST_END, procConfig.proc_rank(),
+ "Ending ghost exchange (still doing checks).");
#endif
-#ifndef NDEBUG
- result = check_sent_ents(allsent);
- RRA("Failed check on shared entities.");
- result = check_all_shared_handles();
- RRA("Failed check on all shared handles.");
-#endif
-#ifdef DEBUG_COMM
- std::cout << "Exiting exchange_ghost_cells" << std::endl;
-#endif
-
//===========================================
// wait if requested
//===========================================
if (wait_all) {
-#ifdef DEBUG_COMM
+#ifdef DEBUG_BARRIER
success = MPI_Barrier(procConfig.proc_comm());
#else
- success = MPI_Waitall(buffProcs.size(), &recv_reqs[0], &status[0]);
+ success = MPI_Waitall(2*buffProcs.size(), &recv_remoteh_reqs[0], &status);
+ success = MPI_Waitall(2*buffProcs.size(), &sendReqs[0], &status);
#endif
if (MPI_SUCCESS != success) {
result = MB_FAILURE;
@@ -4096,9 +4051,193 @@
}
}
+#ifndef NDEBUG
+ result = check_sent_ents(allsent);
+ RRA("Failed check on shared entities.");
+ result = check_all_shared_handles();
+ RRA("Failed check on all shared handles.");
+#endif
+#ifdef DEBUG_COMM
+ std::cerr << "Exiting exchange_ghost_cells" << std::endl; std::cerr.flush();
+#endif
+
return MB_SUCCESS;
}
+MBErrorCode MBParallelComm::send_buffer(const unsigned int to_proc,
+ Buffer *send_buff,
+ int mesg_tag,
+ MPI_Request &send_req,
+ MPI_Request &ack_req,
+ int *ack_buff,
+ int &this_incoming,
+ int next_mesg_tag,
+ Buffer *next_recv_buff,
+ MPI_Request *next_recv_req,
+ int *next_incoming)
+{
+ MBErrorCode result = MB_SUCCESS;
+ int success;
+
+ // if small message, post recv for remote handle message
+ if (send_buff->get_stored_size() <= (int)INITIAL_BUFF_SIZE && next_recv_buff) {
+ (*next_incoming)++;
+ PRINT_DEBUG_IRECV(procConfig.proc_rank(), to_proc, next_recv_buff->mem_ptr,
+ INITIAL_BUFF_SIZE, next_mesg_tag, *next_incoming);
+ success = MPI_Irecv(next_recv_buff->mem_ptr, INITIAL_BUFF_SIZE,
+ MPI_UNSIGNED_CHAR, to_proc,
+ next_mesg_tag, procConfig.proc_comm(),
+ next_recv_req);
+ if (success != MPI_SUCCESS) {
+ result = MB_FAILURE;
+ RRA("Failed to post irecv for next message in ghost exchange.");
+ }
+ }
+ // if large, we'll need an ack before sending the rest
+ else if (send_buff->get_stored_size() > (int)INITIAL_BUFF_SIZE) {
+ this_incoming++;
+ PRINT_DEBUG_IRECV(procConfig.proc_rank(), to_proc, (unsigned char*)ack_buff,
+ sizeof(int), mesg_tag-1, this_incoming);
+ success = MPI_Irecv(ack_buff, sizeof(int),
+ MPI_UNSIGNED_CHAR, to_proc,
+ mesg_tag-1, procConfig.proc_comm(),
+ &ack_req);
+ if (success != MPI_SUCCESS) {
+ result = MB_FAILURE;
+ RRA("Failed to post irecv for entity ack in ghost exchange.");
+ }
+ }
+
+ // send the buffer
+ PRINT_DEBUG_ISEND(procConfig.proc_rank(), to_proc, send_buff->mem_ptr, mesg_tag,
+ std::min(send_buff->get_stored_size(), (int)INITIAL_BUFF_SIZE));
+ assert(0 <= send_buff->get_stored_size() &&
+ send_buff->get_stored_size() <= (int)send_buff->alloc_size);
+ success = MPI_Isend(send_buff->mem_ptr,
+ std::min(send_buff->get_stored_size(),
+ (int)INITIAL_BUFF_SIZE),
+ MPI_UNSIGNED_CHAR, to_proc,
+ mesg_tag, procConfig.proc_comm(), &send_req);
+ if (success != MPI_SUCCESS) return MB_FAILURE;
+
+ return result;
+}
+
+MBErrorCode MBParallelComm::recv_buffer(int mesg_tag_expected,
+ const MPI_Status &mpi_status,
+ Buffer *recv_buff,
+ MPI_Request &recv_req,
+ MPI_Request &ack_recvd_req,
+ int &this_incoming,
+ Buffer *send_buff,
+ MPI_Request &send_req,
+ MPI_Request &sent_ack_req,
+ bool &done,
+ Buffer *next_buff,
+ int next_tag,
+ MPI_Request *next_req,
+ int *next_incoming)
+{
+ // process a received message; if there will be more coming,
+ // post a receive for 2nd part then send an ack message
+ //
+ int from_proc = mpi_status.MPI_SOURCE;
+ int success;
+ MBErrorCode result = MB_SUCCESS;
+
+ // set the buff_ptr on the recv_buffer; needs to point beyond any
+ // valid data already in the buffer
+ recv_buff->reset_ptr(std::min(recv_buff->get_stored_size(),
+ (int)recv_buff->alloc_size));
+
+ if (mpi_status.MPI_TAG == mesg_tag_expected &&
+ recv_buff->get_stored_size() > (int)INITIAL_BUFF_SIZE) {
+ // 1st message & large - allocate buffer, post irecv for 2nd message,
+ // then send ack
+ recv_buff->reserve(recv_buff->get_stored_size());
+ assert(recv_buff->alloc_size > INITIAL_BUFF_SIZE);
+
+ // will expect a 2nd message
+ this_incoming++;
+
+ PRINT_DEBUG_IRECV(procConfig.proc_rank(), from_proc,
+ recv_buff->mem_ptr+INITIAL_BUFF_SIZE,
+ recv_buff->get_stored_size() - INITIAL_BUFF_SIZE,
+ mesg_tag_expected+1, this_incoming);
+ success = MPI_Irecv(recv_buff->mem_ptr+INITIAL_BUFF_SIZE,
+ recv_buff->get_stored_size() - INITIAL_BUFF_SIZE,
+ MPI_UNSIGNED_CHAR, from_proc,
+ mesg_tag_expected+1, procConfig.proc_comm(),
+ &recv_req);
+ if (success != MPI_SUCCESS) {
+ result = MB_FAILURE;
+ RRA("Failed to post 2nd iRecv in ghost exchange.");
+ }
+
+ // send ack, doesn't matter what data actually is
+ PRINT_DEBUG_ISEND(procConfig.proc_rank(), from_proc, recv_buff->mem_ptr,
+ mesg_tag_expected-1, sizeof(int));
+ success = MPI_Isend(recv_buff->mem_ptr, sizeof(int),
+ MPI_UNSIGNED_CHAR, from_proc,
+ mesg_tag_expected-1, procConfig.proc_comm(), &sent_ack_req);
+ if (success != MPI_SUCCESS) {
+ result = MB_FAILURE;
+ RRA("Failed to send ack in ghost exchange.");
+ }
+ }
+
+ else if (mpi_status.MPI_TAG == mesg_tag_expected-1) {
+ // got an ack back, send the 2nd half of message
+
+ // should be a large message if we got this
+ assert(*((size_t*)send_buff->mem_ptr) > INITIAL_BUFF_SIZE);
+
+ // post irecv for next message, then send 2nd message
+ if (next_buff) {
+ // we'll expect a return message
+ (*next_incoming)++;
+ PRINT_DEBUG_IRECV(procConfig.proc_rank(), from_proc, next_buff->mem_ptr,
+ INITIAL_BUFF_SIZE, next_tag, *next_incoming);
+
+ success = MPI_Irecv(next_buff->mem_ptr,
+ INITIAL_BUFF_SIZE,
+ MPI_UNSIGNED_CHAR, from_proc,
+ next_tag, procConfig.proc_comm(),
+ next_req);
+ if (success != MPI_SUCCESS) {
+ result = MB_FAILURE;
+ RRA("Failed to post next irecv in ghost exchange.");
+ }
+
+ }
+
+ // send 2nd message
+ PRINT_DEBUG_ISEND(procConfig.proc_rank(), from_proc,
+ send_buff->mem_ptr+INITIAL_BUFF_SIZE,
+ mesg_tag_expected+1,
+ send_buff->get_stored_size() - INITIAL_BUFF_SIZE);
+
+ assert(send_buff->get_stored_size()-INITIAL_BUFF_SIZE < send_buff->alloc_size &&
+ 0 <= send_buff->get_stored_size());
+ success = MPI_Isend(send_buff->mem_ptr+INITIAL_BUFF_SIZE,
+ send_buff->get_stored_size() - INITIAL_BUFF_SIZE,
+ MPI_UNSIGNED_CHAR, from_proc, mesg_tag_expected+1,
+ procConfig.proc_comm(), &send_req);
+ if (success != MPI_SUCCESS) {
+ result = MB_FAILURE;
+ RRA("Failed to send 2nd message in ghost exchange.");
+ }
+ }
+ else if ((mpi_status.MPI_TAG == mesg_tag_expected &&
+ recv_buff->get_stored_size() <= (int)INITIAL_BUFF_SIZE) ||
+ mpi_status.MPI_TAG == mesg_tag_expected+1) {
+ // message completely received - signal that we're done
+ done = true;
+ }
+
+ return MB_SUCCESS;
+}
+
MBErrorCode MBParallelComm::check_clean_iface(MBRange &allsent)
{
// allsent is all entities I think are on interface; go over them, looking
@@ -4124,6 +4263,10 @@
}
}
if (numz) {
+ for (int i = numz; i > 0; i--) {
+ sharedp[nump-i] = -1;
+ sharedh[nump-i] = 0;
+ }
result = set_sharing_data(*rit, pstatus, nump, nump-numz, sharedp, sharedh);
RRA("");
}
@@ -4163,6 +4306,16 @@
RRA("");
result = mbImpl->tag_set_data(sharedhs_tag(), &ent, 1, hs);
RRA("");
+#ifndef NDEBUG
+ {
+ // check for duplicates in proc list
+ std::set<unsigned int> dumprocs;
+ int dp = 0;
+ for (; dp < old_nump && -1 != ps[dp]; dp++)
+ dumprocs.insert(ps[dp]);
+ assert(dp == (int)dumprocs.size());
+ }
+#endif
}
else {
unsigned int j = (ps[0] == (int)procConfig.proc_rank() ? 1 : 0);
@@ -4250,7 +4403,6 @@
const bool is_iface = !num_layers;
unsigned int ind;
- unsigned char *buff_ptr;
MBParallelComm *pc;
MBErrorCode result = MB_SUCCESS;
@@ -4282,12 +4434,9 @@
//===========================================
for (ind = 0; ind < pc->buffProcs.size(); ind++) {
-
- // buff_ptr points to the END (one past last occupied byte) of buffer
- buff_ptr = &pc->ownerSBuffs[ind][0];
-
// entities
- result = pc->pack_entities(sent_ents[p][ind], pc->ownerSBuffs[ind], buff_ptr,
+ pc->localOwnedBuffs[ind]->reset_ptr(sizeof(int));
+ result = pc->pack_entities(sent_ents[p][ind], pc->localOwnedBuffs[ind],
store_remote_handles, pc->buffProcs[ind], is_iface,
&entprocs[p], &allsent[p]);
RRAI(pc->get_moab(), "Packing entities failed.");
@@ -4322,11 +4471,11 @@
// buffer could be empty, which means there isn't any message to
// unpack (due to this comm proc getting added as a result of indirect
// communication); just skip this unpack
- if (pc->ownerSBuffs[ind].empty()) continue;
+ if (pc->localOwnedBuffs[ind]->get_stored_size() == 0) continue;
unsigned int to_p = pc->buffProcs[ind];
- unsigned char *buff_ptr = &pc->ownerSBuffs[ind][0];
- result = pcs[to_p]->unpack_entities(buff_ptr,
+ pc->localOwnedBuffs[ind]->reset_ptr(sizeof(int));
+ result = pcs[to_p]->unpack_entities(pc->localOwnedBuffs[ind]->buff_ptr,
store_remote_handles, ind, is_iface,
L1hloc[to_p], L1hrem[to_p], L1p[to_p], L2hloc[to_p],
L2hrem[to_p], L2p[to_p], new_ents[to_p]);
@@ -4365,9 +4514,9 @@
for (ind = 0, proc_it = pc->buffProcs.begin();
proc_it != pc->buffProcs.end(); proc_it++, ind++) {
// skip if iface layer and higher-rank proc
- unsigned char *buff_ptr = &pc->ownerSBuffs[ind][0];
+ pc->localOwnedBuffs[ind]->reset_ptr(sizeof(int));
result = pc->pack_remote_handles(L1hloc[p][ind], L1hrem[p][ind], L1p[p][ind], *proc_it,
- pc->ownerSBuffs[ind], buff_ptr);
+ pc->localOwnedBuffs[ind]);
RRAI(pc->get_moab(), "Failed to pack remote handles.");
}
}
@@ -4382,7 +4531,9 @@
proc_it != pc->buffProcs.end(); proc_it++, ind++) {
// incoming remote handles
unsigned int to_p = pc->buffProcs[ind];
- result = pcs[to_p]->unpack_remote_handles(p, &pc->ownerSBuffs[ind][0],
+ pc->localOwnedBuffs[ind]->reset_ptr(sizeof(int));
+ result = pcs[to_p]->unpack_remote_handles(p,
+ pc->localOwnedBuffs[ind]->buff_ptr,
L2hloc[to_p], L2hrem[to_p], L2p[to_p]);
RRAI(pc->get_moab(), "Failed to unpack remote handles.");
}
@@ -4469,20 +4620,21 @@
std::vector<MBEntityHandle> &L1hrem,
std::vector<int> &L1p,
unsigned int to_proc,
- std::vector<unsigned char> &buff,
- unsigned char *&buff_ptr)
+ Buffer *buff)
{
// 2 vectors of handles plus ints
- CHECK_BUFF_SPACE(buff, buff_ptr, ((L1p.size()+1)*sizeof(int) +
- (L1hloc.size()+1)*sizeof(MBEntityHandle) +
- (L1hrem.size()+1)*sizeof(MBEntityHandle)));
+ buff->check_space(((L1p.size()+1)*sizeof(int) +
+ (L1hloc.size()+1)*sizeof(MBEntityHandle) +
+ (L1hrem.size()+1)*sizeof(MBEntityHandle)));
// should be in pairs of handles
- PACK_INT(buff_ptr, L1hloc.size());
- PACK_INTS(buff_ptr, &L1p[0], L1p.size());
- PACK_EH(buff_ptr, &L1hrem[0], L1hrem.size());
- PACK_EH(buff_ptr, &L1hloc[0], L1hloc.size());
+ PACK_INT(buff->buff_ptr, L1hloc.size());
+ PACK_INTS(buff->buff_ptr, &L1p[0], L1p.size());
+ PACK_EH(buff->buff_ptr, &L1hrem[0], L1hrem.size());
+ PACK_EH(buff->buff_ptr, &L1hloc[0], L1hloc.size());
+ buff->set_stored_size();
+
return MB_SUCCESS;
}
@@ -4546,6 +4698,7 @@
RRA("Couldn't get bridge ents in the set.");
// need to get layers of bridge-adj entities
+ if (from_ents.empty()) continue;
result = MeshTopoUtil(mbImpl).get_bridge_adjacencies(from_ents, bridge_dim,
ghost_dim, ghosted_ents,
num_layers);
@@ -4596,29 +4749,38 @@
// post ghost irecv's for all interface procs
// index greqs the same as buffer/sharing procs indices
- std::vector<MPI_Request> recv_reqs(MAX_SHARING_PROCS, MPI_REQUEST_NULL);
- std::vector<MPI_Status> gstatus(MAX_SHARING_PROCS);
+ std::vector<MPI_Request> recv_tag_reqs(2*buffProcs.size(), MPI_REQUEST_NULL),
+ sent_ack_reqs(buffProcs.size(), MPI_REQUEST_NULL);
std::vector<unsigned int>::iterator sit;
int ind;
+
+ reset_all_buffers();
+ int incoming = 0;
+
for (ind = 0, sit = buffProcs.begin(); sit != buffProcs.end(); sit++, ind++) {
- success = MPI_Irecv(&ghostRBuffs[ind][0], ghostRBuffs[ind].size(),
+ incoming++;
+ PRINT_DEBUG_IRECV(*sit, procConfig.proc_rank(), remoteOwnedBuffs[ind]->mem_ptr,
+ INITIAL_BUFF_SIZE, MB_MESG_TAGS_SIZE, incoming);
+
+ success = MPI_Irecv(remoteOwnedBuffs[ind]->mem_ptr, INITIAL_BUFF_SIZE,
MPI_UNSIGNED_CHAR, *sit,
- MB_MESG_ANY, procConfig.proc_comm(),
- &recv_reqs[ind]);
+ MB_MESG_TAGS_SIZE, procConfig.proc_comm(),
+ &recv_tag_reqs[ind]);
if (success != MPI_SUCCESS) {
result = MB_FAILURE;
RRA("Failed to post irecv in ghost exchange.");
}
+
}
// pack and send tags from this proc to others
// make sendReqs vector to simplify initialization
- std::fill(sendReqs, sendReqs+2*buffProcs.size(), MPI_REQUEST_NULL);
-
+ sendReqs.resize(2*buffProcs.size(), MPI_REQUEST_NULL);
+
// take all shared entities if incoming list is empty
if (entities.empty()) entities = sharedEnts;
- unsigned char *buff_ptr;
+ int dum_ack_buff;
for (ind = 0, sit = buffProcs.begin(); sit != buffProcs.end(); sit++, ind++) {
@@ -4651,57 +4813,62 @@
// pack the data
// reserve space on front for size and for initial buff size
- INIT_BUFFER(ownerSBuffs[ind], buff_ptr);
+ localOwnedBuffs[ind]->reset_ptr(sizeof(int));
result = pack_tags(tag_ents,
src_tags, dst_tags, tag_ranges,
- ownerSBuffs[ind], buff_ptr, true, *sit);
+ localOwnedBuffs[ind], true, *sit);
RRA("Failed to count buffer in pack_send_tag.");
// now send it
- result = send_buffer(*sit, &ownerSBuffs[ind][0],
- buff_ptr-&ownerSBuffs[ind][0],
- MB_MESG_TAGS, sendReqs[ind], sendReqs[ind+buffProcs.size()]);
+ result = send_buffer(*sit, localOwnedBuffs[ind], MB_MESG_TAGS_SIZE, sendReqs[2*ind],
+ recv_tag_reqs[2*ind+1], &dum_ack_buff, incoming);
RRA("Failed to send buffer.");
}
// receive/unpack tags
- int num_incoming = exch_procs.size();
-
- while (num_incoming) {
+ while (incoming) {
int ind;
MPI_Status status;
- success = MPI_Waitany(MAX_SHARING_PROCS, &recv_reqs[0], &ind, &status);
+ PRINT_DEBUG_WAITANY(recv_tag_reqs, MB_MESG_TAGS_SIZE, procConfig.proc_rank());
+ success = MPI_Waitany(2*buffProcs.size(), &recv_tag_reqs[0], &ind, &status);
if (MPI_SUCCESS != success) {
result = MB_FAILURE;
RRA("Failed in waitany in ghost exchange.");
}
+ PRINT_DEBUG_RECD(status);
+
// ok, received something; decrement incoming counter
- num_incoming--;
+ incoming--;
- bool done;
+ bool done = false;
MBRange dum_range;
- result = recv_buffer(MB_MESG_TAGS, status,
- ghostRBuffs[ind], recv_reqs[ind], done);
+ result = recv_buffer(MB_MESG_TAGS_SIZE,
+ status,
+ remoteOwnedBuffs[ind/2],
+ recv_tag_reqs[ind], recv_tag_reqs[ind+1],
+ incoming,
+ localOwnedBuffs[ind/2], sendReqs[ind], sendReqs[ind+1],
+ done);
RRA("Failed to resize recv buffer.");
if (done) {
- buff_ptr = &ghostRBuffs[ind][sizeof(int)];
- result = unpack_tags(buff_ptr, dum_range, true, buffProcs[ind]);
+ remoteOwnedBuffs[ind]->reset_ptr(sizeof(int));
+ result = unpack_tags(remoteOwnedBuffs[ind]->buff_ptr,
+ dum_range, true, buffProcs[ind]);
RRA("Failed to recv-unpack-tag message.");
}
- else {
- num_incoming++;
- continue;
- }
}
// ok, now wait
-// MPI_Status status[MAX_SHARING_PROCS];
+#ifdef DEBUG_BARRIER
success = MPI_Barrier(procConfig.proc_comm());
-// success = MPI_Waitall(2*buffProcs.size(), &sendReqs[0], status);
+#else
+ MPI_Status status;
+ success = MPI_Waitall(2*buffProcs.size(), &sendReqs[0], status);
+#endif
if (MPI_SUCCESS != success) {
result = MB_FAILURE;
RRA("Failure in waitall in tag exchange.");
@@ -4773,7 +4940,7 @@
RRA("Failed to count buffer in pack_send_tag.");
unsigned char *buff_ptr = &ownerSBuffs[ind][0];
- CHECK_BUFF_SPACE(ownerSBuffs[ind], buff_ptr, buff_size);
+ buff->check_space(ownerSBuffs[ind], buff_ptr, buff_size);
PACK_INT( buff_ptr, 1 ); // number of tags
result = pack_tag( src_tag, dst_tag, proc_ents[*sit], proc_ents[*sit],
ownerSBuffs[ind], buff_ptr, true, *sit );
@@ -5642,7 +5809,7 @@
// send sizes
assert(num_proc == (int)send_data.size());
- std::fill(sendReqs, sendReqs+buffProcs.size(), MPI_REQUEST_NULL);
+ sendReqs.resize(buffProcs.size(), MPI_REQUEST_NULL);
for (int i = 0; i < num_proc; ++i) {
sizes_send[i] = send_data[i].size();
ierr = MPI_Isend( &sizes_send[i], 1, MPI_INT, buffProcs[i], tag, comm, &sendReqs[i] );
Modified: MOAB/trunk/parallel/MBParallelComm.hpp
===================================================================
--- MOAB/trunk/parallel/MBParallelComm.hpp 2009-11-25 21:22:39 UTC (rev 3388)
+++ MOAB/trunk/parallel/MBParallelComm.hpp 2009-11-30 23:06:35 UTC (rev 3389)
@@ -32,6 +32,9 @@
#include <map>
#include <set>
#include <vector>
+#include <iostream>
+#include <fstream>
+#include <assert.h>
#include "math.h"
#include "MBmpi.h"
@@ -484,14 +487,31 @@
MBInterface* get_moab() const { return mbImpl; }
+ class Buffer {
+ public:
+ unsigned char *mem_ptr;
+ unsigned char *buff_ptr;
+ unsigned int alloc_size;
+
+ Buffer(unsigned int sz = 0);
+ Buffer(const Buffer &);
+ ~Buffer();
+ void reset_buffer(size_t buff_pos = 0) {reset_ptr(buff_pos); reserve(INITIAL_BUFF_SIZE);}
+ void reset_ptr(size_t buff_pos = 0) {assert((!mem_ptr && !buff_pos)|| (alloc_size >= buff_pos)); buff_ptr = mem_ptr + buff_pos;}
+ void reserve(unsigned int new_size);
+ void set_stored_size() {*((int*)mem_ptr) = (int)(buff_ptr - mem_ptr);}
+ int get_stored_size() {return *((int*)mem_ptr);}
+
+ void check_space(unsigned int addl_space);
+ };
+
//! public 'cuz we want to unit test these externally
MBErrorCode pack_buffer(MBRange &orig_ents,
const bool adjacencies,
const bool tags,
const bool store_remote_handles,
const int to_proc,
- std::vector<unsigned char> &buff,
- int &buff_size);
+ Buffer *buff);
MBErrorCode unpack_buffer(unsigned char *buff_ptr,
const bool store_remote_handles,
@@ -506,8 +526,7 @@
MBRange &new_ents);
MBErrorCode pack_entities(MBRange &entities,
- std::vector<unsigned char> &buff,
- unsigned char *&buff_ptr,
+ Buffer *buff,
const bool store_remote_handles,
const int to_proc,
const bool is_iface,
@@ -580,13 +599,14 @@
std::vector<MBEntityHandle> &L1hrem,
std::vector<int> &procs,
unsigned int to_proc,
- std::vector<unsigned char> &buff,
- unsigned char *&buff_ptr);
+ Buffer *buff);
MBErrorCode list_entities(const MBEntityHandle *ents, int num_ents);
MBErrorCode list_entities(const MBRange &ents);
+ static const unsigned int INITIAL_BUFF_SIZE;
+
private:
// common initialization code, called from various constructors
@@ -651,19 +671,34 @@
//! send the indicated buffer, possibly sending size first
MBErrorCode send_buffer(const unsigned int to_proc,
- const unsigned char *send_buff,
- const unsigned int buff_size,
- const int msg_type,
- MPI_Request &send_req1,
- MPI_Request &send_req2);
+ Buffer *send_buff,
+ const int msg_tag,
+ MPI_Request &send_req,
+ MPI_Request &ack_recv_req,
+ int *ack_buff,
+ int &this_incoming,
+ int next_mesg_tag = -1,
+ Buffer *next_recv_buff = NULL,
+ MPI_Request *next_recv_req = NULL,
+ int *next_incoming = NULL);
- //! use integer size in buffer to resize buffer, then post an
- //! Irecv to get message
+ //! process incoming message; if longer than the initial size, post
+ //! recv for next part then send ack; if ack, send second part; else
+ //! indicate that we're done and buffer is ready for processing
MBErrorCode recv_buffer(int mesg_tag_expected,
const MPI_Status &mpi_status,
- std::vector<unsigned char> &recv_buff,
- MPI_Request &recv_req,
- bool &done);
+ Buffer *recv_buff,
+ MPI_Request &recv_2nd_req,
+ MPI_Request &ack_req,
+ int &this_incoming,
+ Buffer *send_buff,
+ MPI_Request &send_req,
+ MPI_Request &sent_ack_req,
+ bool &done,
+ Buffer *next_buff = NULL,
+ int next_tag = -1,
+ MPI_Request *next_req = NULL,
+ int *next_incoming = NULL);
//! pack a range of entities with equal # verts per entity, along with
//! the range on the sending proc
@@ -672,8 +707,7 @@
const int to_proc,
MBRange &these_ents,
MBRange &entities,
- std::vector<unsigned char> &buff,
- unsigned char *&buff_ptr);
+ Buffer *buff);
MBErrorCode print_buffer(unsigned char *buff_ptr, int mesg_type, int from_proc,
bool sent);
@@ -686,8 +720,7 @@
std::vector<MBEntityHandle> &recd_ents);
MBErrorCode pack_sets(MBRange &entities,
- std::vector<unsigned char> &buff,
- unsigned char *&buff_ptr,
+ Buffer *buff,
const bool store_handles,
const int to_proc);
@@ -806,8 +839,7 @@
const std::vector<MBTag> &src_tags,
const std::vector<MBTag> &dst_tags,
const std::vector<MBRange> &tag_ranges,
- std::vector<unsigned char> &buff,
- unsigned char *&buff_ptr,
+ Buffer *buff,
const bool store_handles,
const int to_proc);
@@ -849,8 +881,7 @@
MBTag destination_tag,
const MBRange &entities,
const MBRange &whole_range,
- std::vector<unsigned char> &buff,
- unsigned char *&buff_ptr,
+ Buffer *buff,
const bool store_remote_handles,
const int to_proc );
@@ -999,10 +1030,16 @@
SequenceManager *sequenceManager;
//! more data buffers, proc-specific
- std::vector<std::vector<unsigned char> > ownerSBuffs, ghostRBuffs;
+ std::vector<Buffer*> localOwnedBuffs, remoteOwnedBuffs;
+ //! reset message buffers to their initial state
+ void reset_all_buffers();
+
+ //! delete all buffers, freeing up any memory held by them
+ void delete_all_buffers();
+
//! request objects, may be used if store_remote_handles is used
- MPI_Request sendReqs[2*MAX_SHARING_PROCS];
+ std::vector<MPI_Request> sendReqs;
//! processor rank for each buffer index
std::vector<unsigned int> buffProcs;
@@ -1020,10 +1057,95 @@
int globalPartCount; //!< Cache of global part count
MBEntityHandle partitioningSet; //!< entity set containing all parts
+
+ std::ofstream myFile;
int pcommID;
+
};
+inline MBParallelComm::Buffer::Buffer(const Buffer &other_buff)
+{
+ alloc_size = other_buff.alloc_size;
+ mem_ptr = (unsigned char *)malloc(alloc_size);
+ memcpy(mem_ptr, other_buff.mem_ptr, alloc_size);
+ buff_ptr = mem_ptr + (other_buff.buff_ptr - other_buff.mem_ptr);
+}
+
+inline MBParallelComm::Buffer::Buffer(unsigned int new_size)
+ : mem_ptr(NULL), buff_ptr(NULL), alloc_size(0)
+{
+ if (new_size) this->reserve(new_size);
+}
+
+inline MBParallelComm::Buffer::~Buffer()
+{
+ if (mem_ptr) {
+ free(mem_ptr);
+ mem_ptr = NULL;
+ }
+}
+
+#define DEBUG_BUFFER 1
+
+inline void MBParallelComm::Buffer::reserve(unsigned int new_size) {
+
+#ifdef DEBUG_BUFFER
+ int tmp_pos = 0;
+ if (mem_ptr) {
+ tmp_pos = buff_ptr - mem_ptr;
+ }
+ buff_ptr = (unsigned char *)malloc(new_size);
+ assert(0 <= tmp_pos && tmp_pos <= (int)alloc_size);
+ if (tmp_pos) memcpy(buff_ptr, mem_ptr, tmp_pos);
+ if (mem_ptr) free(mem_ptr);
+ mem_ptr = buff_ptr;
+ alloc_size = new_size;
+ buff_ptr = mem_ptr + tmp_pos;
+#else
+ if (mem_ptr && alloc_size < new_size) {
+ size_t tmp_pos = mem_ptr ? buff_ptr - mem_ptr : 0;
+ mem_ptr = (unsigned char *)realloc(mem_ptr, new_size);
+ alloc_size = new_size;
+ buff_ptr = mem_ptr + tmp_pos;
+ }
+ else if (!mem_ptr) {
+ mem_ptr = (unsigned char *)malloc(new_size);
+ alloc_size = new_size;
+ buff_ptr = mem_ptr;
+ }
+#endif
+}
+
+inline void MBParallelComm::Buffer::check_space(unsigned int addl_space )
+{
+ assert(buff_ptr >= mem_ptr && buff_ptr <= mem_ptr+alloc_size);
+ unsigned int new_size = buff_ptr - mem_ptr + addl_space;
+ if (new_size > alloc_size)
+ reserve(1.5*new_size);
+}
+
+inline void MBParallelComm::reset_all_buffers()
+{
+ std::vector<Buffer*>::iterator vit;
+ for (vit = localOwnedBuffs.begin(); vit != localOwnedBuffs.end(); vit++)
+ (*vit)->reset_buffer();
+ for (vit = remoteOwnedBuffs.begin(); vit != remoteOwnedBuffs.end(); vit++)
+ (*vit)->reset_buffer();
+}
+
+inline void MBParallelComm::delete_all_buffers()
+{
+ std::vector<Buffer*>::iterator vit;
+ for (vit = localOwnedBuffs.begin(); vit != localOwnedBuffs.end(); vit++)
+ delete (*vit);
+ localOwnedBuffs.clear();
+
+ for (vit = remoteOwnedBuffs.begin(); vit != remoteOwnedBuffs.end(); vit++)
+ delete (*vit);
+ remoteOwnedBuffs.clear();
+}
+
inline std::vector<unsigned int> &MBParallelComm::buff_procs()
{
return buffProcs;
Modified: MOAB/trunk/parallel/mbparallelcomm_test.cpp
===================================================================
--- MOAB/trunk/parallel/mbparallelcomm_test.cpp 2009-11-25 21:22:39 UTC (rev 3388)
+++ MOAB/trunk/parallel/mbparallelcomm_test.cpp 2009-11-30 23:06:35 UTC (rev 3389)
@@ -401,10 +401,8 @@
MBParallelComm *pcomm = new MBParallelComm(mbImpl);
- std::vector<unsigned char> buff(1024);
- int buff_size;
- result = pcomm->pack_buffer(ents, false, true, false, -1,
- buff, buff_size);
+ MBParallelComm::Buffer buff;
+ result = pcomm->pack_buffer(ents, false, true, false, -1, &buff);
RRA("Packing buffer count (non-stored handles) failed.");
std::vector<std::vector<MBEntityHandle> > L1hloc, L1hrem;
@@ -412,7 +410,8 @@
std::vector<MBEntityHandle> L2hloc, L2hrem;
std::vector<unsigned int> L2p;
- result = pcomm->unpack_buffer(&buff[0], false, -1, -1, L1hloc, L1hrem, L1p, L2hloc,
+ buff.reset_ptr();
+ result = pcomm->unpack_buffer(buff.buff_ptr, false, -1, -1, L1hloc, L1hrem, L1p, L2hloc,
L2hrem, L2p, new_ents);
RRA("Unpacking buffer (non-stored handles) failed.");
Modified: MOAB/trunk/parallel/pcomm_serial.cpp
===================================================================
--- MOAB/trunk/parallel/pcomm_serial.cpp 2009-11-25 21:22:39 UTC (rev 3388)
+++ MOAB/trunk/parallel/pcomm_serial.cpp 2009-11-30 23:06:35 UTC (rev 3389)
@@ -7,6 +7,11 @@
#include "TestUtil.hpp"
#include <vector>
+void print_usage(char *argv)
+{
+ std::cout << "Usage: " << argv << " nprocs filename" << std::endl;
+}
+
int main( int argc, char* argv[] )
{
#ifdef USE_MPI
@@ -14,9 +19,10 @@
#endif
if (1 < argc && !strcmp(argv[1], "-h")) {
- std::cout << "Usage: " << argv[0] << " nprocs filename" << std::endl;
+ print_usage(argv[0]);
return 0;
}
+
int nprocs = 2;
std::string ptag_name("GEOM_DIMENSION");
std::vector<int> partition_tag_vals;
@@ -34,6 +40,11 @@
if (argc > 4) partition_tag_vals.push_back(atoi(argv[4]));
}
else partition_tag_vals.push_back(3);
+
+ if (0 == nprocs) {
+ print_usage(argv[0]);
+ return 1;
+ }
MBErrorCode rval;
MBCore *moab = new MBCore[nprocs]();
@@ -74,7 +85,7 @@
CHECK_ERR(rval);
// now 1 layer of hex ghosts
- rval = MBParallelComm::exchange_ghost_cells(&pc[0], nprocs, 3, 0, 1, true);
+ rval = MBParallelComm::exchange_ghost_cells(&pc[0], nprocs, 3, 2, 1, true);
CHECK_ERR(rval);
for (int i = 0; i < nprocs; i++)
Modified: MOAB/trunk/parallel/pcomm_unit.cpp
===================================================================
--- MOAB/trunk/parallel/pcomm_unit.cpp 2009-11-25 21:22:39 UTC (rev 3388)
+++ MOAB/trunk/parallel/pcomm_unit.cpp 2009-11-30 23:06:35 UTC (rev 3389)
@@ -92,8 +92,6 @@
}
MBParallelComm *pcomm = new MBParallelComm( &moab );
- int size = 0;
- std::vector<unsigned char> buff;
std::vector<int> addl_procs;
// get the necessary vertices too
@@ -103,9 +101,12 @@
CHECK_ERR(rval);
entities.merge(tmp_range);
+ MBParallelComm::Buffer buff(MBParallelComm::INITIAL_BUFF_SIZE);
+ buff.reset_ptr(sizeof(int));
rval = pcomm->pack_buffer( entities, false, true, false,
- -1, buff, size);
+ -1, &buff);
CHECK_ERR(rval);
+ buff.set_stored_size();
delete pcomm;
moab.~MBCore();
@@ -118,8 +119,9 @@
std::vector<std::vector<int> > L1p;
std::vector<MBEntityHandle> L2hloc, L2hrem;
std::vector<unsigned int> L2p;
- rval = pcomm->unpack_buffer( &buff[0], false, -1, -1, L1hloc, L1hrem, L1p, L2hloc,
- L2hrem, L2p, entities);
+ buff.reset_ptr(sizeof(int));
+ rval = pcomm->unpack_buffer(buff.buff_ptr, false, -1, -1, L1hloc, L1hrem, L1p, L2hloc,
+ L2hrem, L2p, entities);
CHECK_ERR(rval);
delete pcomm;
Modified: MOAB/trunk/tools/iMesh/iMeshP_unit_tests.cpp
===================================================================
--- MOAB/trunk/tools/iMesh/iMeshP_unit_tests.cpp 2009-11-25 21:22:39 UTC (rev 3388)
+++ MOAB/trunk/tools/iMesh/iMeshP_unit_tests.cpp 2009-11-30 23:06:35 UTC (rev 3389)
@@ -684,7 +684,8 @@
iBase_EntitySetHandle root_set;
iMesh_getRootSet( imesh, &root_set, &ierr );
- iMeshP_loadAll( imesh, prtn, root_set, FILENAME, 0, &ierr, strlen(FILENAME), 0 );
+ const char *opt = ";;PARTITION=PARALLEL_PARTITION";
+ iMeshP_loadAll( imesh, prtn, root_set, FILENAME, opt, &ierr, strlen(FILENAME), strlen(opt) );
PCHECK;
1
0
This now produces error messages like
[0/2] MOAB Error: MB_NOT_IMPLEMENTED : mbpc->resolve_shared_ents(0, -1, -1)
in resolve_and_exchange at ../../parallel/scdtest.cpp:208
[1/2] MOAB Error: MB_NOT_IMPLEMENTED : mbpc->resolve_shared_ents(0, -1, -1)
in resolve_and_exchange at ../../parallel/scdtest.cpp:208
--------------------------------------------------------------------------
MPI_ABORT was invoked on rank 1 in communicator MPI_COMM_WORLD
with errorcode 9.
Note that the line number is correct. The former behavior gave only
Error: MOAB function failed
lt-scdtest: ../../parallel/scdtest.cpp:203: void error(MBErrorCode): Assertion `0' failed.
[kunyang:31680] *** Process received signal ***
---
parallel/scdtest.cpp | 22 ++++++++++++++--------
1 files changed, 14 insertions(+), 8 deletions(-)
diff --git a/parallel/scdtest.cpp b/parallel/scdtest.cpp
index 64ca4d8..6269129 100644
--- a/parallel/scdtest.cpp
+++ b/parallel/scdtest.cpp
@@ -40,7 +40,20 @@ int size;
void set_local_domain_bounds();
void create_hexes_and_verts();
void resolve_and_exchange();
-void error(MBErrorCode err);
+
+#define error(err) do { \
+ MBErrorCode e; \
+ if((e = (err)) != MB_SUCCESS) { \
+ cerr << "[" << rank << "/" << size << "] MOAB Error: " \
+ << mbint->get_error_string(e) << " : " << #err \
+ << "\n\tin " << __FUNCTION__ << " at " << __FILE__ \
+ << ":" << __LINE__ << endl; \
+ cerr.flush(); \
+ sleep(1); \
+ MPI_Abort(MPI_COMM_WORLD,e); \
+ } \
+ } while (0)
+
int main(int argc, char *argv[])
{
@@ -196,10 +209,3 @@ void resolve_and_exchange()
error(mbpc->exchange_ghost_cells(-1, 0, 1, true));
}
-void error(MBErrorCode err)
-{
- if(err != MB_SUCCESS) {
- cerr << "Error: MOAB function failed\n";
- assert(0);
- }
-}
--
1.6.5.3
1
0
Author: wilsonp
Date: 2009-11-25 08:59:22 -0600 (Wed, 25 Nov 2009)
New Revision: 3386
Modified:
MOAB/trunk/ReadABAQUS.hpp
Log:
Add documentation for meta-data of ABAQUS mesh.
Modified: MOAB/trunk/ReadABAQUS.hpp
===================================================================
--- MOAB/trunk/ReadABAQUS.hpp 2009-11-25 14:15:47 UTC (rev 3385)
+++ MOAB/trunk/ReadABAQUS.hpp 2009-11-25 14:59:22 UTC (rev 3386)
@@ -27,6 +27,154 @@
// Owner : Paul Wilson
//-------------------------------------------------------------------------
+/** Implementation of ABAQUS mesh hierarchy and meta-data on MOAB
+
+
+This reader processes data written by the ABAQUS computer-aided engineering
+front-end. While that tool writes binary files in its own proprietary format,
+it also writes an ASCII input file that is the fundamental input to the
+ABAQUS solver itself. A published syntax for this format is available from Simulia.
+
+This reader only supports a subset of the mesh syntax necessary to support
+a basic thermal analysis of solid systems.
+
+An ABAQUS mesh makes use of the common paradigms of building a
+geometry as an "assembly" of "instances" of "parts".
+
+A "part" is defined as a set of "nodes" and "elements" connecting
+those nodes. The nodes and elements can be arranged in "node sets" and
+"element sets" and specific "materials" can be assigned to "element
+sets" other features of parts are not currently used by applications
+and are not implemented.
+
+
+Overview of supported sructure
+
+* File:
+ * Heading
+ * Part
+ * Nodes
+ * Elements
+ * Node Sets
+ * Element Sets
+ * Solid Sections
+ * Assembly
+ * Instance
+ * Node Sets
+
+
+An "instance" is a full copy of a "part" with a linear geometric
+transformation. To create a full copy:
+• a duplicate set of nodes is created by copying the coordinates of
+ the part nodes and applying a linear geometric transformation - the
+ new coords are used to define the new nodes
+• a new node set is created for each node set in the part and the set
+ of nodes among the duplicates are assigned to the new node set
+• a duplicate set of elements is defined by creating a new element
+ with a connectivity made up of the duplicate nodes that correspond
+ to the appropriate original element
+• a new element set is created for each element set in the part and
+ the set of elements among the duplicates are assigned to the new
+ element set; the corresponding material is also assigned go the new
+ element sets
+
+In order to provide convenient access to the data and mesh structures
+the following data model is used:
+
+• MBEntitySet file_set
+ • tags
+ • NONE
+ • members
+ • all nodes of all parts and all instances
+ • all elements of all parts and all instances
+ • all assembly_sets
+ • all part_sets
+• MBEntitySet part_set
+ • tags
+ • mSetNameTag (opaque=char*)
+ name of entitity set
+ • members
+ • part nodes
+ • part elements
+ • part node sets
+ • part element sets
+• MBEntitySet assembly_set
+ • tags
+ • mSetNameTag (opaque=char*)
+ name of entitity set
+ • members
+ • instance_sets
+ • instanec element_sets
+ • instance node_sets
+ • instance nodes
+ • instance elements
+• MBEntitySet instance_set
+ • tags
+ • mSetNameTag (opaque=char*)
+ name of entitity set
+ • mPartHandleTag (handle)
+ pointer to part from which this instance was generated
+ • mAssemblyHandleTag (handle)
+ pointer to assembly in which this instance exists
+ • mInstancePIDTag (int)
+ ordinal number indicating which instance of this part
+ • mInstanceGIDTag (int)
+ ordinal number indicating which instance in this assembly
+ • members
+ • instance nodes
+ • instance elements
+ • instance node_sets
+ • instanec element_sets
+• MBEntitySet node_set
+ • tags
+ • mSetNameTag (opaque=char*)
+ name of entitity set
+ • mPartHandleTag (handle)
+ pointer to part in which this node set exists
+ • mInstanceHandleTag (handle)
+ pointer back to instance set in which this node set exists
+ (NULL if this node_set is not in an instance)
+ • mAssemblyHandleTag (handle)
+ pointer to assembly in which this node set exists
+ (NULL if this node_set is not in an assembly)
+ • members
+ • nodes
+• MBEntitySet element_set
+ • tags
+ • mSetNameTag (opaque=char*)
+ name of entitity set
+ • mPartHandleTag (handle)
+ pointer to part in which this element set exists
+ • mInstanceHandleTag (handle)
+ pointer back to instance set in which this element set exists
+ (NULL if this node_set is not in an instance)
+ • mAssemblyHandleTag (handle)
+ pointer to assembly in which this element set exists
+ (NULL if this node_set is not in an assembly)
+ • mMatNameTag (opaque=char*)
+ name of material in these elements
+ • mMaterialSetTag (integer)
+ material id in these elements
+ • members
+ • elements
+• MBEntity node
+ • tags
+ • mLocalIDTag (int)
+ numerical ID of node in local scope (part, instance)
+ • mInstanceHandleTag (handle)
+ pointer back to instance set in which this node exists
+ (NULL if this node is not in an instance)
+• MBEntity element
+ • tags
+ • mLocalIDTag (int)
+ numerical ID of element in local scope (part, instance)
+ • mInstanceHandleTag (handle)
+ pointer back to instance set in which this element exists
+ (NULL if this element is not in an instance)
+
+
+ **/
+
#ifndef READABAQUS_HPP
#define READABAQUS_HPP
1
0
Author: wilsonp
Date: 2009-11-25 08:15:47 -0600 (Wed, 25 Nov 2009)
New Revision: 3385
Modified:
MOAB/trunk/tools/dagmc/DagMC.cpp
Log:
Add some error handling in parsing metadata.
Modified: MOAB/trunk/tools/dagmc/DagMC.cpp
===================================================================
--- MOAB/trunk/tools/dagmc/DagMC.cpp 2009-11-24 21:22:30 UTC (rev 3384)
+++ MOAB/trunk/tools/dagmc/DagMC.cpp 2009-11-25 14:15:47 UTC (rev 3385)
@@ -1087,13 +1087,17 @@
int cellid,matid;
double imp, density;
- MBI->tag_get_data( idTag , &(*iter), 1, &cellid );
- MBI->tag_get_data(impTag , &(*iter), 1, &imp );
- MBI->tag_get_data(matTag , &(*iter), 1, &matid );
+ rval = MBI->tag_get_data( idTag , &(*iter), 1, &cellid );
+ if (MB_SUCCESS != rval) return rval;
+ rval = MBI->tag_get_data(impTag , &(*iter), 1, &imp );
+ if (MB_SUCCESS != rval) return rval;
+ rval = MBI->tag_get_data(matTag , &(*iter), 1, &matid );
+ if (MB_SUCCESS != rval) return rval;
if (0 == matid) {
cgmfile << cellid << " " << matid << " imp:n=" << imp ;
} else {
- MBI->tag_get_data(densTag, &(*iter), 1, &density );
+ rval = MBI->tag_get_data(densTag, &(*iter), 1, &density );
+ if (MB_SUCCESS != rval) return rval;
cgmfile << cellid << " " << matid << " " << density << " imp:n=" << imp ;
}
if (*iter == impl_compl_handle)
@@ -1109,13 +1113,17 @@
int surfid, bc_id;
- MBI->tag_get_data( idTag, &(*iter), 1, &surfid );
- MBI->tag_get_data( bcTag, &(*iter), 1, &bc_id );
+ rval = MBI->tag_get_data( idTag, &(*iter), 1, &surfid );
+ if (MB_SUCCESS != rval) return rval;
+ rval = MBI->tag_get_data( bcTag, &(*iter), 1, &bc_id );
+ if (MB_SUCCESS != rval && MB_TAG_NOT_FOUND != rval) return rval;
- if (BC_SPEC == bc_id)
- cgmfile << "*";
- if (BC_WHITE == bc_id)
- cgmfile << "+";
+ if (MB_TAG_NOT_FOUND != rval) {
+ if (BC_SPEC == bc_id)
+ cgmfile << "*";
+ if (BC_WHITE == bc_id)
+ cgmfile << "+";
+ }
cgmfile << surfid << std::endl;
}
1
0
Author: kraftche
Date: 2009-11-20 13:12:44 -0600 (Fri, 20 Nov 2009)
New Revision: 3380
Modified:
MOAB/trunk/MBSkinner.cpp
Log:
o Change skinner to use now faster bit tags. Results in better performance
when skinning subsets of the mesh at the cost of slightly worse performance
when skinning the entire mesh. Could probably be even better if the
bit tag code were cleaned up and optimized a bit.
o Now that bit tag default values work correctly, skip allocation of tag
data for bit tags when skinning the entire mesh.
Modified: MOAB/trunk/MBSkinner.cpp
===================================================================
--- MOAB/trunk/MBSkinner.cpp 2009-11-20 19:00:50 UTC (rev 3379)
+++ MOAB/trunk/MBSkinner.cpp 2009-11-20 19:12:44 UTC (rev 3380)
@@ -1002,11 +1002,6 @@
return result;
}
-// Bit tag uses less memory, but is slower. Probably
-// because we have to query one entity at a time.
-// -- j.kraftcheck 2009-11-10
-const bool use_bit_tag = false;
-
MBErrorCode MBSkinner::find_skin_vertices( const MBRange& entities,
MBRange* skin_verts,
MBRange* skin_elems,
@@ -1022,23 +1017,33 @@
if (dim < 1 || dim > 3 || !entities.all_of_dimension(dim))
return MB_TYPE_OUT_OF_RANGE;
- // create a bit tag for use in a) tagging skin vertices, and
- // b) fast intersection with input entities range.
+ // are we skinning all entities
+ size_t count = entities.size();
+ int num_total;
+ rval = thisMB->get_number_entities_by_dimension( 0, dim, num_total );
+ if (MB_SUCCESS != rval)
+ return rval;
+ bool all = (count == (size_t)num_total);
+
+ // Create a bit tag for fast intersection with input entities range.
+ // If we're skinning all the entities in the mesh, we really don't
+ // need the tag. To save memory, just create it with a default value
+ // of one and don't set it. That way MOAB will return 1 for all
+ // entities.
MBTag tag;
- char bit = 0;
- rval = thisMB->tag_create( NULL, 1, use_bit_tag ? MB_TAG_BIT : MB_TAG_DENSE, tag, &bit );
+ char bit = all ? 1 : 0;
+ rval = thisMB->tag_create( NULL, 1, MB_TAG_BIT, tag, &bit );
if (MB_SUCCESS != rval)
return rval;
// tag all entities in input range
- size_t count = entities.size();
- char* vect = new char[count];
- memset( vect, 1, count );
- rval = thisMB->tag_set_data( tag, entities, vect );
- delete [] vect;
- if (MB_SUCCESS != rval) {
- thisMB->tag_delete(tag);
- return rval;
+ if (!all) {
+ std::vector<unsigned char> vect(count, 1);
+ rval = thisMB->tag_set_data( tag, entities, &vect[0] );
+ if (MB_SUCCESS != rval) {
+ thisMB->tag_delete(tag);
+ return rval;
+ }
}
switch (dim) {
1
0
Author: kraftche
Date: 2009-11-20 13:00:50 -0600 (Fri, 20 Nov 2009)
New Revision: 3379
Modified:
MOAB/trunk/MBBits.cpp
MOAB/trunk/MBBits.hpp
MOAB/trunk/MBInterface.hpp
MOAB/trunk/MBSkinner.cpp
MOAB/trunk/MBTest.cpp
MOAB/trunk/ReadHDF5.cpp
MOAB/trunk/TagServer.cpp
MOAB/trunk/TagServer.hpp
MOAB/trunk/WriteHDF5.cpp
Log:
o Allow get/set of bit tags for multiple entities in one call. Bits are
unpacked such that a byte is returned for each entity, with the tag value
stored in the lower bits (the same as was done for single entities before.)
o Fix inconsistent handling of default value for bits tags. When querying
a bit tag with a default value for some entity for which it was not set,
the previous code could do any of the following: successfully return zero,
successfully return the default value, or return failure, depending on
details of the internal representation.
o Add more tests for bit tag functionality.
o Update a couple places in code that might benefit from querying many
bit tags at once.
o Document behavior of query functions in MBInterface for bit tags and
multiple entities.
Modified: MOAB/trunk/MBBits.cpp
===================================================================
--- MOAB/trunk/MBBits.cpp 2009-11-20 17:58:25 UTC (rev 3378)
+++ MOAB/trunk/MBBits.cpp 2009-11-20 19:00:50 UTC (rev 3379)
@@ -64,7 +64,222 @@
return MB_SUCCESS;
}
+
+MBErrorCode MBBitPage::get_entities_with_value( unsigned char value,
+ int offset,
+ int count,
+ int num_bits_per_flag,
+ MBEntityHandle first,
+ MBRange& results ) const
+{
+ if (mBitArray) {
+ MBRange::iterator hint = results.begin();
+ for (int i = 0; i < count; ++i)
+ if (value == MBBitManipulator::get_bits( (offset+i)*num_bits_per_flag,
+ num_bits_per_flag, mBitArray))
+ hint = results.insert( hint, first + i );
+ }
+ return MB_SUCCESS;
+}
+void MBBitPage::alloc_array( int num_bits_per_flag,
+ const unsigned char* default_value )
+{
+ assert(!mBitArray);
+
+ mBitArray = new unsigned char[mPageSize];
+ // Modifed by J.Kraftcheck : 31 Jan, 2008:
+ // Need to initialize to default value to ensure that we return
+ // the default value for unset entities.
+
+ // Zero memory if no default value. Also, if default value is
+ // zero, we can zero all the memory w/out worring about the
+ // number of bits per entity.
+ if (!default_value || !*default_value)
+ memset(mBitArray, 0, mPageSize);
+ // Otherwise initialize memory using default value
+ else {
+ // Mask unused bits of default value so that we can set
+ // individual bits using bitwise-OR w/out having to worry
+ // about masking unwanted stuff.
+ unsigned char defval = (*default_value) & ((1u << num_bits_per_flag) - 1);
+
+ switch (num_bits_per_flag) {
+ // If number of bits is a power of two (a byte contains a whole
+ // number of tag bit values) then use memset to initialize the memory.
+ // Note fall-through for switch cases: for 1-bit tags we first
+ // copy the lsb into the adjacent bit, then fall through to 2-bit
+ // case, copying last two bits into next two, and so on.
+ case 1: defval |= (defval << 1);
+ case 2: defval |= (defval << 2);
+ case 4: defval |= (defval << 4);
+ case 8: memset( mBitArray, defval, mPageSize );
+ break;
+ // If num_bits_per_flag is not a power of two, then values do
+ // not align with byte boundaries. Need to initialize values
+ // individually.
+ default:
+ memset(mBitArray, 0, mPageSize);
+ // Subtract 1 from mPageSize because last byte is unused, allowing
+ // questionable MBBitManipulator code to read/write 1 past end
+ // of array.
+ for (int i = 0; i < 8 * (mPageSize-1); i += num_bits_per_flag)
+ MBBitManipulator::set_bits( i, num_bits_per_flag, defval, mBitArray );
+ }
+ }
+}
+
+
+MBErrorCode MBBitPageGroup::get_bits( MBEntityHandle start,
+ MBEntityID count,
+ unsigned char* bits,
+ const unsigned char* def_val)
+{
+ MBErrorCode result = MB_SUCCESS, tmp_result;
+
+
+ MBEntityID id = ID_FROM_HANDLE(start);
+ MBEntityHandle page = id/mOffsetFactor;
+ MBEntityID offset = id%mOffsetFactor;
+ MBEntityID pcount = mOffsetFactor - offset;
+ while (count) {
+ if (pcount > count)
+ pcount = count;
+
+ if (page >= mBitPagesSize) {
+ memset( bits, def_val ? *def_val : 0, count );
+ break;
+ }
+
+ tmp_result = mBitPages[page]->get_bits( offset, pcount, mBitsPerFlag, bits, def_val);
+ if (MB_SUCCESS != tmp_result) {
+ memset( bits, 0, pcount );
+ result = tmp_result;
+ }
+
+ count -= pcount;
+ bits += pcount;
+ ++page;
+ offset = 0;
+ pcount = mOffsetFactor;
+ }
+
+ return result;
+}
+
+MBErrorCode MBBitPageGroup::set_bits( MBEntityHandle start,
+ MBEntityID count,
+ const unsigned char* bits,
+ const unsigned char* def_val)
+{
+ MBErrorCode result = MB_SUCCESS, tmp_result;
+ MBEntityID id = ID_FROM_HANDLE(start);
+ MBEntityHandle page = id/mOffsetFactor;
+ MBEntityID offset = id%mOffsetFactor;
+ MBEntityID pcount = mOffsetFactor - offset;
+ while (count) {
+ if (pcount > count)
+ pcount = count;
+
+ if (page >= mBitPagesSize) {
+ for(int j = page - mBitPagesSize +1; j--;)
+ mBitPages.push_back(new MBBitPage());
+ mBitPagesSize = mBitPages.size();
+ }
+
+ tmp_result = mBitPages[page]->set_bits( offset, pcount, mBitsPerFlag, bits, def_val);
+ if (MB_SUCCESS != tmp_result) {
+ result = tmp_result;
+ }
+
+ count -= pcount;
+ bits += pcount;
+ ++page;
+ offset = 0;
+ pcount = mOffsetFactor;
+ }
+
+ return result;
+}
+
+
+MBErrorCode MBBitPageGroup::get_entities_with_value( unsigned char value,
+ MBEntityHandle first,
+ MBEntityHandle last,
+ MBRange& results )
+{
+ MBErrorCode rval;
+ assert(last >= first);
+ MBEntityID count = last - first + 1;
+
+ MBEntityID id = ID_FROM_HANDLE(first);
+ MBEntityHandle page = id/mOffsetFactor;
+ MBEntityID offset = id%mOffsetFactor;
+ MBEntityID pcount = mOffsetFactor - offset;
+ while (count && page < mBitPagesSize) {
+ if (pcount > count)
+ pcount = count;
+
+ rval = mBitPages[page]->get_entities_with_value( value, offset, pcount, mBitsPerFlag, first, results );
+ if (MB_SUCCESS != rval)
+ return rval;
+
+ first += pcount;
+ count -= pcount;
+ ++page;
+ offset = 0;
+ pcount = mOffsetFactor;
+ }
+
+ return MB_SUCCESS;
+}
+
+MBErrorCode MBBitServer::set_bits( MBTagId tag_id,
+ const MBRange& handles,
+ const unsigned char* data,
+ const unsigned char* default_val)
+{
+ --tag_id; // First ID is 1.
+ if(tag_id >= mBitPageGroups[0].size() || mBitPageGroups[0][tag_id] == NULL)
+ return MB_TAG_NOT_FOUND;
+
+ MBErrorCode rval;
+ MBRange::const_pair_iterator i;
+ for (i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i) {
+ MBEntityType type = TYPE_FROM_HANDLE(i->first);
+ assert(TYPE_FROM_HANDLE(i->second) == type); // should be true because id of zero is never used
+ MBEntityID count = i->second - i->first + 1;
+ rval = mBitPageGroups[type][tag_id]->set_bits(i->first, count, data, default_val);
+ if (MB_SUCCESS != rval)
+ return rval;
+ data += count;
+ }
+ return MB_SUCCESS;
+}
+
+MBErrorCode MBBitServer::get_bits( MBTagId tag_id,
+ const MBRange& handles,
+ unsigned char* data,
+ const unsigned char* default_val)
+{
+ --tag_id; // First ID is 1.
+ if(tag_id >= mBitPageGroups[0].size() || mBitPageGroups[0][tag_id] == NULL)
+ return MB_TAG_NOT_FOUND;
+
+ MBErrorCode rval;
+ MBRange::const_pair_iterator i;
+ for (i = handles.const_pair_begin(); i != handles.const_pair_end(); ++i) {
+ MBEntityType type = TYPE_FROM_HANDLE(i->first);
+ assert(TYPE_FROM_HANDLE(i->second) == type); // should be true because id of zero is never used
+ MBEntityID count = i->second - i->first + 1;
+ rval = mBitPageGroups[type][tag_id]->get_bits(i->first, count, data, default_val);
+ if (MB_SUCCESS != rval)
+ return rval;
+ data += count;
+ }
+ return MB_SUCCESS;
+}
+
/*! give back a tag id that was used to set and get bits */
MBErrorCode MBBitServer::release_tag_id(MBTagId tag_id)
{
@@ -192,51 +407,50 @@
return result;
}
-MBErrorCode MBBitServer::get_entities_with_tag_value(MBTagId tag_id,
- MBEntityType type,
- MBRange& entities,
- const unsigned char bits)
+MBErrorCode MBBitServer::get_entities_with_tag_value( MBTagId tag_id,
+ MBEntityType type,
+ MBRange& entities,
+ const unsigned char bits)
{
- MBRange possibles;
- MBErrorCode result = get_entities(tag_id, type, possibles);
- if (MB_SUCCESS != result || possibles.empty()) return result;
- MBErrorCode tmp_result;
- unsigned char dum = 0;
- for (MBRange::iterator it = possibles.begin(); it != possibles.end(); it++) {
- tmp_result = get_bits(tag_id, *it, dum);
- if (dum == bits) entities.insert(*it);
- if (tmp_result != MB_SUCCESS) result = tmp_result;
- }
-
- return result;
+ --tag_id; // First ID is 1.
+ if(tag_id >= mBitPageGroups[type].size() || mBitPageGroups[type][tag_id] == NULL)
+ return MB_TAG_NOT_FOUND;
+
+ return mBitPageGroups[type][tag_id]->
+ get_entities_with_value( bits, FIRST_HANDLE(type), LAST_HANDLE(type), entities );
}
-MBErrorCode MBBitServer::get_entities_with_tag_value(const MBRange &range,
- MBTagId tag_id, MBEntityType type,
- MBRange& entities,
- const unsigned char bits)
+MBErrorCode MBBitServer::get_entities_with_tag_value( const MBRange &range,
+ MBTagId tag_id,
+ MBEntityType type,
+ MBRange& entities,
+ const unsigned char bits)
{
- MBRange temp1, temp2;
- MBErrorCode result = get_entities(tag_id, type, temp1);
- if (MB_SUCCESS != result) return result;
- std::set_intersection(range.begin(), range.end(),
- temp1.begin(), temp1.end(), mb_range_inserter(temp2));
- if (temp2.empty()) return result;
-
- unsigned char dum = 0;
- MBErrorCode tmp_result;
- for (MBRange::iterator it = temp2.begin(); it != temp2.end(); it++) {
- tmp_result = get_bits(tag_id, *it, dum);
- if (dum == bits) entities.insert(*it);
- if (tmp_result != MB_SUCCESS) result = tmp_result;
+ --tag_id; // First ID is 1.
+ if(tag_id >= mBitPageGroups[0].size() || mBitPageGroups[0][tag_id] == NULL)
+ return MB_TAG_NOT_FOUND;
+
+ MBErrorCode rval;
+ MBRange::const_pair_iterator i;
+ for (i = range.const_pair_begin(); i != range.const_pair_end(); ++i) {
+ MBEntityType this_type = TYPE_FROM_HANDLE(i->first);
+ assert(TYPE_FROM_HANDLE(i->second) == this_type); // should be true because id of zero is never used
+ if (type < this_type)
+ continue;
+ if (type > this_type)
+ break;
+
+ rval = mBitPageGroups[type][tag_id]->
+ get_entities_with_value( bits, i->first, i->second, entities );
+ if (MB_SUCCESS != rval)
+ return rval;
}
-
- return result;
+ return MB_SUCCESS;
}
MBErrorCode MBBitServer::get_number_entities( const MBTagId tag_id,
- const MBEntityType type,
- int& num_entities)
+ const MBEntityType type,
+ int& num_entities)
{
MBRange dum_range;
MBErrorCode result = get_entities(tag_id, type, dum_range);
Modified: MOAB/trunk/MBBits.hpp
===================================================================
--- MOAB/trunk/MBBits.hpp 2009-11-20 17:58:25 UTC (rev 3378)
+++ MOAB/trunk/MBBits.hpp 2009-11-20 19:00:50 UTC (rev 3379)
@@ -179,12 +179,30 @@
}
//! get the bits from a bit page
- MBErrorCode get_bits(int offset, int num_bits_per_flag, unsigned char& bits);
+ MBErrorCode get_bits(int offset, int num_bits_per_flag, unsigned char& bits,
+ const unsigned char* default_value);
//! set the bits in a bit page
MBErrorCode set_bits(int offset, int num_bits_per_flag, unsigned char bits,
const unsigned char* default_value);
+ //! get the bits from a bit page
+ MBErrorCode get_bits(int offset, int count, int num_bits_per_flag,
+ unsigned char* bits,
+ const unsigned char* default_value);
+
+ //! set the bits in a bit page
+ MBErrorCode set_bits(int offset, int count, int num_bits_per_flag,
+ const unsigned char* bits,
+ const unsigned char* default_value);
+
+ MBErrorCode get_entities_with_value( unsigned char value,
+ int offset,
+ int count,
+ int num_bits_per_flag,
+ MBEntityHandle first,
+ MBRange& results ) const;
+
//! set the bits in a bit page only if space has been allocated
MBErrorCode weak_set_bits(int offset, int num_bits_per_flag, unsigned char bits);
@@ -193,6 +211,8 @@
private:
//! bit array uses lazy allocation
unsigned char* mBitArray;
+
+ void alloc_array( int num_bits_per_flag, const unsigned char* default_value );
//! don't allow copying of these bit pages
MBBitPage(const MBBitPage&)
@@ -217,13 +237,15 @@
takes how many bits to get
return bits
*/
-inline MBErrorCode MBBitPage::get_bits(int offset, int num_bits_per_flag, unsigned char& bits)
+inline MBErrorCode MBBitPage::get_bits(int offset, int num_bits_per_flag,
+ unsigned char& bits,
+ const unsigned char* def_val)
{
// because the default bits are 0x0,
// we'll return that if no memory has been allocated
if(!mBitArray)
{
- bits = 0;
+ bits = def_val ? *def_val : 0;
return MB_SUCCESS;
}
@@ -233,66 +255,64 @@
return MB_SUCCESS;
}
+inline MBErrorCode MBBitPage::get_bits(int offset, int count,
+ int num_bits_per_flag,
+ unsigned char* bits,
+ const unsigned char* def_val)
+{
+ // because the default bits are 0x0,
+ // we'll return that if no memory has been allocated
+ if(!mBitArray)
+ {
+ memset( bits, def_val ? *def_val : 0, count );
+ return MB_SUCCESS;
+ }
+ // get bits using bit manipulator
+ for (int i = 0; i < count; ++i)
+ bits[i] = MBBitManipulator::get_bits(
+ (offset+i)*num_bits_per_flag, num_bits_per_flag, mBitArray);
+
+ return MB_SUCCESS;
+}
+
+
/*! set the bits in a bit page
takes bit offset into the page
takes how many bits to set
takes the bits to set
*/
-inline MBErrorCode MBBitPage::set_bits(int offset,
- int num_bits_per_flag, unsigned char bits,
- const unsigned char* default_value)
+inline MBErrorCode MBBitPage::set_bits( int offset,
+ int num_bits_per_flag,
+ unsigned char bits,
+ const unsigned char* default_value)
{
// if memory hasn't been allocated, allocate it and zero the memory
if(!mBitArray)
- {
- mBitArray = new unsigned char[mPageSize];
- // Modifed by J.Kraftcheck : 31 Jan, 2008:
- // Need to initialize to default value to ensure that we return
- // the default value for unset entities.
-
- // Zero memory if no default value. Also, if default value is
- // zero, we can zero all the memory w/out worring about the
- // number of bits per entity.
- if (!default_value || !*default_value)
- memset(mBitArray, 0, mPageSize);
- // Otherwise initialize memory using default value
- else {
- // Mask unused bits of default value so that we can set
- // individual bits using bitwise-OR w/out having to worry
- // about masking unwanted stuff.
- unsigned char defval = (*default_value) & ((1u << num_bits_per_flag) - 1);
-
- switch (num_bits_per_flag) {
- // If number of bits is a power of two (a byte contains a whole
- // number of tag bit values) then use memset to initialize the memory.
- // Note fall-through for switch cases: for 1-bit tags we first
- // copy the lsb into the adjacent bit, then fall through to 2-bit
- // case, copying last two bits into next two, and so on.
- case 1: defval |= (defval << 1);
- case 2: defval |= (defval << 2);
- case 4: defval |= (defval << 4);
- case 8: memset( mBitArray, defval, mPageSize );
- break;
- // If num_bits_per_flag is not a power of two, then values do
- // not align with byte boundaries. Need to initialize values
- // individually.
- default:
- memset(mBitArray, 0, mPageSize);
- // Subtract 1 from mPageSize because last byte is unused, allowing
- // questionable MBBitManipulator code to read/write 1 past end
- // of array.
- for (int i = 0; i < 8 * (mPageSize-1); i += num_bits_per_flag)
- MBBitManipulator::set_bits( i, num_bits_per_flag, defval, mBitArray );
- }
- }
- }
+ alloc_array( num_bits_per_flag, default_value );
// set the bits using bit manipulator
return MBBitManipulator::set_bits(
offset*num_bits_per_flag, num_bits_per_flag, bits, mBitArray);
}
+inline MBErrorCode MBBitPage::set_bits( int offset, int count,
+ int num_bits_per_flag,
+ const unsigned char* bits,
+ const unsigned char* default_value)
+{
+ // if memory hasn't been allocated, allocate it and zero the memory
+ if(!mBitArray)
+ alloc_array( num_bits_per_flag, default_value );
+ // set the bits using bit manipulator
+ for (int i = 0; i < count; ++i)
+ MBBitManipulator::set_bits( (offset+i)*num_bits_per_flag,
+ num_bits_per_flag,
+ bits[i], mBitArray );
+ return MB_SUCCESS;
+}
+
+
/*! weak set bits only sets bits if memory has been allocated
takes bit offset
takes number of bits to set
@@ -331,16 +351,32 @@
}
//! get bits from bit pages
- MBErrorCode get_bits(MBEntityHandle handle, unsigned char& bits);
+ MBErrorCode get_bits(MBEntityHandle handle, unsigned char& bits,
+ const unsigned char* default_value);
//! set bits in bit pages
MBErrorCode set_bits(MBEntityHandle handle, unsigned char bits,
const unsigned char* default_value);
+ //! get bits from bit pages
+ MBErrorCode get_bits(MBEntityHandle start, MBEntityID count,
+ unsigned char* data,
+ const unsigned char* default_value);
+
+ //! set bits in bit pages
+ MBErrorCode set_bits(MBEntityHandle start, MBEntityID count,
+ const unsigned char* data,
+ const unsigned char* default_value);
+
//! set bits in bit pages only if the bit page allocated memory
MBErrorCode weak_set_bits(MBEntityHandle handle, unsigned char bits);
MBErrorCode get_entities(MBEntityType type, MBRange& entities);
+
+ MBErrorCode get_entities_with_value( unsigned char value,
+ MBEntityHandle first,
+ MBEntityHandle last,
+ MBRange& results );
//! if this page group contains this entity, return true, otherwise false
bool contains(const MBEntityHandle handle) const;
@@ -391,7 +427,9 @@
takes entity handle
return the bits
*/
-inline MBErrorCode MBBitPageGroup::get_bits(MBEntityHandle handle, unsigned char& bits)
+inline MBErrorCode MBBitPageGroup::get_bits(MBEntityHandle handle,
+ unsigned char& bits,
+ const unsigned char* def_val)
{
// strip off the entity type
handle = ID_FROM_HANDLE(handle);
@@ -399,14 +437,14 @@
unsigned int which_page = handle / mOffsetFactor;
// if the page isn't there, just return 0x0
- if(which_page >= mBitPagesSize)
- {
- bits = 0;
- return MB_TAG_NOT_FOUND;
+ if(which_page >= mBitPagesSize) {
+ bits = def_val ? *def_val : 0;
+ return MB_SUCCESS;
}
// return bits from bit page
- return mBitPages[which_page]->get_bits( (handle - ( which_page * mOffsetFactor )), mBitsPerFlag, bits);
+ return mBitPages[which_page]->get_bits( (handle - ( which_page * mOffsetFactor )),
+ mBitsPerFlag, bits, def_val);
}
/*! set the bits in bit pages
@@ -504,11 +542,26 @@
//! release a tag id for reuse
MBErrorCode release_tag_id(MBTagId tag_id);
- //! get the bits associated with an entity handle
- MBErrorCode get_bits(MBTagId tag_id, MBEntityHandle handle, unsigned char& bits);
+ //! get the bits associated with entity handles
+ MBErrorCode get_bits(MBTagId tag_id,
+ const MBEntityHandle* handles,
+ int num_handles,
+ unsigned char* data,
+ const unsigned char* default_value);
+ MBErrorCode get_bits(MBTagId tag_id,
+ const MBRange& handles,
+ unsigned char* data,
+ const unsigned char* default_value);
//! set the bits associated with an entity handle
- MBErrorCode set_bits(MBTagId tag_id, MBEntityHandle handle, unsigned char bits,
+ MBErrorCode set_bits(MBTagId tag_id,
+ const MBEntityHandle* handles,
+ int num_handles,
+ const unsigned char* data,
const unsigned char* default_value);
+ MBErrorCode set_bits(MBTagId tag_id,
+ const MBRange& handles,
+ const unsigned char* data,
+ const unsigned char* default_value);
//! set the bits associated with an entity handle, only if memory has been allocated
MBErrorCode weak_set_bits(MBTagId tag_id, MBEntityHandle handle, unsigned char bits);
@@ -559,28 +612,46 @@
};
/*! get some bits based on a tag id and handle */
-inline MBErrorCode MBBitServer::get_bits(MBTagId tag_id,
- MBEntityHandle handle, unsigned char& bits)
+inline
+MBErrorCode MBBitServer::get_bits( MBTagId tag_id,
+ const MBEntityHandle* handles,
+ int num_handles,
+ unsigned char* data,
+ const unsigned char* default_val)
{
--tag_id; // First ID is 1.
- if(tag_id >= (*mBitPageGroups).size() || (*mBitPageGroups)[tag_id] == NULL)
- return MB_FAILURE;
+ if(tag_id >= mBitPageGroups[0].size() || mBitPageGroups[0][tag_id] == NULL)
+ return MB_TAG_NOT_FOUND;
- return mBitPageGroups[TYPE_FROM_HANDLE(handle)][tag_id]->get_bits(handle, bits);
-
+ MBErrorCode rval;
+ for (int i = 0; i < num_handles; ++i) {
+ rval = mBitPageGroups[TYPE_FROM_HANDLE(handles[i])][tag_id]
+ ->get_bits(handles[i], data[i], default_val);
+ if (MB_SUCCESS != rval)
+ return rval;
+ }
+ return MB_SUCCESS;
}
-/*! set some bits based on a tag id and handle */
-inline MBErrorCode MBBitServer::set_bits( MBTagId tag_id,
- MBEntityHandle handle,
- unsigned char bits,
- const unsigned char* default_value )
+inline
+MBErrorCode MBBitServer::set_bits( MBTagId tag_id,
+ const MBEntityHandle* handles,
+ int num_handles,
+ const unsigned char* data,
+ const unsigned char* default_val)
{
--tag_id; // First ID is 1.
- if(tag_id >= mBitPageGroupsSize || (*mBitPageGroups)[tag_id] == NULL)
- return MB_FAILURE;
+ if(tag_id >= mBitPageGroups[0].size() || mBitPageGroups[0][tag_id] == NULL)
+ return MB_TAG_NOT_FOUND;
- return mBitPageGroups[TYPE_FROM_HANDLE(handle)][tag_id]->set_bits(handle, bits, default_value);
+ MBErrorCode rval;
+ for (int i = 0; i < num_handles; ++i) {
+ rval = mBitPageGroups[TYPE_FROM_HANDLE(handles[i])][tag_id]
+ ->set_bits(handles[i], data[i], default_val);
+ if (MB_SUCCESS != rval)
+ return rval;
+ }
+ return MB_SUCCESS;
}
/*! set some bits based on a tag id and handle only if memory has been allocated*/
Modified: MOAB/trunk/MBInterface.hpp
===================================================================
--- MOAB/trunk/MBInterface.hpp 2009-11-20 17:58:25 UTC (rev 3378)
+++ MOAB/trunk/MBInterface.hpp 2009-11-20 19:00:50 UTC (rev 3379)
@@ -1143,8 +1143,11 @@
//! Get the value of the indicated tag on the specified entities in the specified vector
/** Get the value of the indicated tag on the specified entities; <em>tag_data</em> must contain
- enough space (i.e. tag_size*num_entities bytes or bits) to hold all tag data. MB does <em>not</em>
+ enough space (i.e. tag_size*num_entities bytes) to hold all tag data. MOAB does <em>not</em>
check whether this space is available before writing to it.
+ \note For bit tags, tag_data must contain one byte per entity. For each
+ entity, the corresponding byte will contain the tag bits in the
+ lower bit positions and zero bits in the higher.
\param tag_handle Tag whose values are being queried.
\param entity_handles 1d vector of entity handles whose tag values are being queried
\param num_entities Number of entities in 1d vector of entity handles
@@ -1168,6 +1171,9 @@
//! Set the value of the indicated tag on the specified entities in the specified vector
/** Set the value of the indicated tag on the specified entities; <em>tag_data</em> contains the
values, <em>one value per entity in <em>entity_handles</em></em>.
+ \note For bit tags, tag_data must contain one byte per entity. For each
+ entity, the tag bits will be read from the lower bits of the
+ corresponding byte.
\param tag_handle Tag whose values are being set
\param entity_handles 1d vector of entity handles whose tag values are being set
\param num_entities Number of entities in 1d vector of entity handles
@@ -1192,6 +1198,7 @@
/**\brief Get pointers to tag data
*
* For a tag, get the values for a list of passed entity handles.
+ *\note This function may not be used for bit tags.
*\param tag_handle The tag
*\param entity_handles An array of entity handles for which to retreive tag values.
*\param num_entities The length of the 'entity_handles' array.
@@ -1211,6 +1218,7 @@
/**\brief Get pointers to tag data
*
* For a tag, get the values for a list of passed entity handles.
+ *\note This function may not be used for bit tags.
*\param tag_handle The tag
*\param entity_handles The entity handles for which to retreive tag values.
*\param tag_data An array of 'const void*'. Array is populated (output)
@@ -1227,6 +1235,7 @@
/**\brief Set tag data given an array of pointers to tag values.
*
* For a tag, set the values for a list of passed entity handles.
+ *\note This function may not be used for bit tags.
*\param tag_handle The tag
*\param entity_handles An array of entity handles for which to set tag values.
*\param num_entities The length of the 'entity_handles' array.
@@ -1246,6 +1255,7 @@
/**\brief Set tag data given an array of pointers to tag values.
*
* For a tag, set the values for a list of passed entity handles.
+ *\note This function may not be used for bit tags.
*\param tag_handle The tag
*\param entity_handles The entity handles for which to set tag values.
*\param tag_data An array of 'const void*'. Array is expected to
Modified: MOAB/trunk/MBSkinner.cpp
===================================================================
--- MOAB/trunk/MBSkinner.cpp 2009-11-20 17:58:25 UTC (rev 3378)
+++ MOAB/trunk/MBSkinner.cpp 2009-11-20 19:00:50 UTC (rev 3379)
@@ -1031,27 +1031,15 @@
return rval;
// tag all entities in input range
- if (use_bit_tag) {
- bit = '\001';
- for (MBRange::const_iterator it = entities.begin(); it != entities.end(); ++it) {
- rval = thisMB->tag_set_data( tag, &*it, 1, &bit );
- if (MB_SUCCESS != rval) {
- thisMB->tag_delete(tag);
- return rval;
- }
- }
+ size_t count = entities.size();
+ char* vect = new char[count];
+ memset( vect, 1, count );
+ rval = thisMB->tag_set_data( tag, entities, vect );
+ delete [] vect;
+ if (MB_SUCCESS != rval) {
+ thisMB->tag_delete(tag);
+ return rval;
}
- else {
- size_t count = entities.size();
- char* vect = new char[count];
- memset( vect, 1, count );
- rval = thisMB->tag_set_data( tag, entities, vect );
- delete [] vect;
- if (MB_SUCCESS != rval) {
- thisMB->tag_delete(tag);
- return rval;
- }
- }
switch (dim) {
case 1:
@@ -1101,7 +1089,6 @@
std::vector<char> tag_vals;
std::vector<MBEntityHandle> adj;
int count;
- char bit;
for (MBRange::const_iterator it = verts.begin(); it != verts.end(); ++it) {
adj.clear();
rval = thisMB->get_adjacencies( &*it, 1, 1, false, adj );
@@ -1110,21 +1097,10 @@
continue;
// remove those not in the input list
- if (use_bit_tag) {
- count = 0;
- for (i = adj.begin(); i != adj.end(); ++i) {
- rval = thisMB->tag_get_data( tag, &*i, 1, &bit );
- if (MB_SUCCESS != rval) return rval;
- if (bit)
- ++count;
- }
- }
- else {
- tag_vals.resize( adj.size() );
- rval = thisMB->tag_get_data( tag, &adj[0], adj.size(), &tag_vals[0] );
- if (MB_SUCCESS != rval) return rval;
- count = std::count( tag_vals.begin(), tag_vals.end(), '\001' );
- }
+ tag_vals.resize( adj.size() );
+ rval = thisMB->tag_get_data( tag, &adj[0], adj.size(), &tag_vals[0] );
+ if (MB_SUCCESS != rval) return rval;
+ count = std::count( tag_vals.begin(), tag_vals.end(), '\001' );
if (count == 1) {
hint = skin_verts.insert( hint, *it );
@@ -1352,7 +1328,6 @@
std::vector<MBEntityHandle> storage;
const MBEntityHandle *conn;
int len;
- char bit;
bool find_edges = skin_edges || create_edges;
MBEntityHandle face;
@@ -1380,26 +1355,15 @@
// remove those not in the input list
i = j = adj.begin();
- if (use_bit_tag) {
- for (; i != adj.end(); ++i) {
- rval = thisMB->tag_get_data( tag, &*i, 1, &bit );
- if (MB_SUCCESS != rval) return rval;
- if (bit)
- *(j++) = *i;
- }
- adj.erase( j, adj.end() );
- }
- else {
- tag_vals.resize( adj.size() );
- rval = thisMB->tag_get_data( tag, &adj[0], adj.size(), &tag_vals[0] );
- if (MB_SUCCESS != rval) return rval;
-
- i = j = adj.begin();
- for (; i != adj.end(); ++i)
- if (tag_vals[i - adj.begin()])
- *(j++) = *i;
- adj.erase( j, adj.end() );
- }
+ tag_vals.resize( adj.size() );
+ rval = thisMB->tag_get_data( tag, &adj[0], adj.size(), &tag_vals[0] );
+ if (MB_SUCCESS != rval) return rval;
+
+ i = j = adj.begin();
+ for (; i != adj.end(); ++i)
+ if (tag_vals[i - adj.begin()])
+ *(j++) = *i;
+ adj.erase( j, adj.end() );
// For each adjacent face, check the edges adjacent to the current vertex
adj_edges.clear(); // other vertex for adjacent edges
@@ -1521,7 +1485,6 @@
std::vector<MBEntityHandle> storage, storage2;
const MBEntityHandle *conn, *conn2;
int len, len2;
- char bit;
bool find_faces = skin_faces || create_faces;
int clen, side, sense, offset, indices[9];
MBEntityType face_type;
@@ -1552,24 +1515,13 @@
// remove those not in the input list
i = j = adj.begin();
- if (use_bit_tag) {
- for (; i != adj.end(); ++i) {
- rval = thisMB->tag_get_data( tag, &*i, 1, &bit );
- if (MB_SUCCESS != rval) return rval;
- if (bit)
- *(j++) = *i;
- }
- adj.erase( j, adj.end() );
- }
- else {
- tag_vals.resize( adj.size() );
- rval = thisMB->tag_get_data( tag, &adj[0], adj.size(), &tag_vals[0] );
- if (MB_SUCCESS != rval) return rval;
- for (; i != adj.end(); ++i)
- if (tag_vals[i - adj.begin()])
- *(j++) = *i;
- adj.erase( j, adj.end() );
- }
+ tag_vals.resize( adj.size() );
+ rval = thisMB->tag_get_data( tag, &adj[0], adj.size(), &tag_vals[0] );
+ if (MB_SUCCESS != rval) return rval;
+ for (; i != adj.end(); ++i)
+ if (tag_vals[i - adj.begin()])
+ *(j++) = *i;
+ adj.erase( j, adj.end() );
// Build lists of sides of 3D element adjacent to the current vertex
adj_quads.clear(); // store three other vertices for each adjacent quad face
Modified: MOAB/trunk/MBTest.cpp
===================================================================
--- MOAB/trunk/MBTest.cpp 2009-11-20 17:58:25 UTC (rev 3378)
+++ MOAB/trunk/MBTest.cpp 2009-11-20 19:00:50 UTC (rev 3379)
@@ -3420,7 +3420,56 @@
if(bits != ((*iter) & 0x7))
return MB_FAILURE;
}
+
+ // test range-based query for all vertices
+ std::vector<unsigned char> data(entities.size());
+ success = MB->tag_get_data( bit_tag, entities, &data[0] );
+ if (MB_SUCCESS != success) return success;
+ std::vector<unsigned char>::iterator i = data.begin();
+ for (iter = entities.begin(); iter != entities.end(); ++iter, ++i)
+ if (*i != ((*iter) & 0x7))
+ return MB_FAILURE;
+ // test vector-based query for all vertices
+ std::vector<MBEntityHandle> verts(entities.begin(), entities.end());
+ success = MB->tag_get_data( bit_tag, &verts[0], verts.size(), &data[0] );
+ if (MB_SUCCESS != success) return success;
+ i = data.begin();
+ for (iter = entities.begin(); iter != entities.end(); ++iter, ++i)
+ if (*i != ((*iter) & 0x7))
+ return MB_FAILURE;
+
+ // test default value
+ const unsigned char default_bits = '\005'; // 0000 0101
+ MBTag tag2;
+ success = MB->tag_create( "bit with default", 4, MB_TAG_BIT, tag2, &default_bits );
+ if (MB_SUCCESS != success) {
+ cout << "Failed to create bit tag with default value" << std::endl;
+ return success;
+ }
+
+ // set value to zero on a single vertex
+ bits = 0;
+ MBEntityHandle zh = verts[verts.size()/2];
+ success = MB->tag_set_data( tag2, &zh, 1, &bits );
+ if (MB_SUCCESS != success)
+ return success;
+
+ // get tag values for all entities
+ data.clear();
+ data.resize( verts.size(), 0x7A ); // initialize with 0111 1010
+ success = MB->tag_get_data( tag2, entities, &data[0] );
+ if (MB_SUCCESS != success)
+ return success;
+
+ // check values
+ i = data.begin();
+ for (iter = entities.begin(); iter != entities.end(); ++iter, ++i)
+ if (*iter == zh && *i) // the one we set to zero
+ return MB_FAILURE;
+ else if (*iter != zh && *i != default_bits)
+ return MB_FAILURE;
+
return MB_SUCCESS;
}
Modified: MOAB/trunk/ReadHDF5.cpp
===================================================================
--- MOAB/trunk/ReadHDF5.cpp 2009-11-20 17:58:25 UTC (rev 3378)
+++ MOAB/trunk/ReadHDF5.cpp 2009-11-20 19:00:50 UTC (rev 3379)
@@ -3038,18 +3038,8 @@
return error(rval);
}
-/*** FIX ME - need to do one at a time for BIT tags! This is stupid. ***/
- if (mbtype == MB_TYPE_BIT)
- {
- rval = MB_SUCCESS;
- for ( ; MB_SUCCESS == rval && i < j; ++i)
- rval = iFace->tag_set_data( tag_handle, idbuf + i, 1, databuf + i );
- }
- else
- {
- rval = iFace->tag_set_data( tag_handle, idbuf + i, j - i, databuf + i*read_size );
- i = j;
- }
+ rval = iFace->tag_set_data( tag_handle, idbuf + i, j - i, databuf + i*read_size );
+ i = j;
if (MB_SUCCESS != rval)
return error(rval);
} // for(ever)
Modified: MOAB/trunk/TagServer.cpp
===================================================================
--- MOAB/trunk/TagServer.cpp 2009-11-20 17:58:25 UTC (rev 3378)
+++ MOAB/trunk/TagServer.cpp 2009-11-20 19:00:50 UTC (rev 3379)
@@ -223,37 +223,6 @@
}
-//! set the value of a tag
-MBErrorCode TagServer::set_bits(const MBTag tag_handle, const MBEntityHandle entity_handle, unsigned char data )
-{
- if(TYPE_FROM_HANDLE(entity_handle) >= MBMAXTYPE)
- return MB_TYPE_OUT_OF_RANGE;
- const TagInfo* info = get_tag_info( tag_handle );
- if (!info)
- return MB_TAG_NOT_FOUND;
- return mBitServer->set_bits(ID_FROM_TAG_HANDLE(tag_handle), entity_handle, data,
- reinterpret_cast<const unsigned char*>(info->default_value()));
-}
-
-//! get the value of a tag
-MBErrorCode TagServer::get_bits(const MBTag tag_handle, const MBEntityHandle entity_handle, unsigned char& data )
-{
- if(TYPE_FROM_HANDLE(entity_handle) >= MBMAXTYPE)
- return MB_TYPE_OUT_OF_RANGE;
- MBErrorCode rval = mBitServer->get_bits(ID_FROM_TAG_HANDLE(tag_handle), entity_handle, data);
- if (MB_TAG_NOT_FOUND == rval) {
- const TagInfo* info = get_tag_info( tag_handle );
- if (!info)
- return MB_FAILURE;
- if (info->default_value())
- data = *reinterpret_cast<const unsigned char*>(info->default_value());
- else
- data = '\0';
- return MB_SUCCESS;
- }
- return rval;
-}
-
MBErrorCode TagServer::set_mesh_data( const MBTag tag_handle,
const void* data,
int size )
@@ -301,12 +270,14 @@
break;
case MB_TAG_BIT:
- if (num_entities == 1)
- rval = sequenceManager->check_valid_entities( entity_handles, num_entities );
+ if (!(tag_info = get_tag_info( tag_id, tag_type )))
+ rval = MB_TAG_NOT_FOUND;
else
- rval = MB_FAILURE;
+ rval = sequenceManager->check_valid_entities( entity_handles, num_entities );
if (MB_SUCCESS == rval)
- rval = set_bits( tag_handle, *entity_handles, *reinterpret_cast<const unsigned char*>(data) );
+ rval= mBitServer->set_bits( tag_id, entity_handles, num_entities,
+ reinterpret_cast<const unsigned char*>(data),
+ reinterpret_cast<const unsigned char*>(tag_info->default_value()));
break;
default:
@@ -340,12 +311,14 @@
break;
case MB_TAG_BIT:
- if (entity_handles.size() == 1)
- rval = sequenceManager->check_valid_entities( entity_handles );
+ if (!(tag_info = get_tag_info( tag_id, tag_type )))
+ rval = MB_TAG_NOT_FOUND;
else
- rval = MB_FAILURE;
+ rval = sequenceManager->check_valid_entities( entity_handles );
if (MB_SUCCESS == rval)
- rval = set_bits( tag_handle, entity_handles.front(), *reinterpret_cast<const unsigned char*>(data) );
+ rval= mBitServer->set_bits( tag_id, entity_handles,
+ reinterpret_cast<const unsigned char*>(data),
+ reinterpret_cast<const unsigned char*>(tag_info->default_value()));
break;
default:
@@ -386,12 +359,7 @@
break;
case MB_TAG_BIT:
- if (num_entities == 1)
- rval = sequenceManager->check_valid_entities( entity_handles, num_entities );
- else
- rval = MB_FAILURE;
- if (MB_SUCCESS == rval)
- rval = set_bits( tag_handle, *entity_handles, *reinterpret_cast<const unsigned char*>(*data) );
+ rval = MB_FAILURE;
break;
default:
@@ -431,12 +399,7 @@
break;
case MB_TAG_BIT:
- if (entity_handles.size() == 1)
- rval = sequenceManager->check_valid_entities( entity_handles );
- else
- rval = MB_FAILURE;
- if (MB_SUCCESS == rval)
- rval = set_bits( tag_handle, entity_handles.front(), *reinterpret_cast<const unsigned char*>(*data) );
+ rval = MB_FAILURE;
break;
default:
@@ -517,11 +480,9 @@
case MB_TAG_SPARSE:
return mSparseData->get_data( tag_id, entity_handles, num_entities, data, default_val );
case MB_TAG_BIT:
- if (num_entities == 1)
- return get_bits( tag_handle, *entity_handles, *reinterpret_cast<unsigned char*>(data) );
- else
- return MB_FAILURE;
-
+ return mBitServer->get_bits( tag_id, entity_handles, num_entities,
+ reinterpret_cast<unsigned char*>(data),
+ reinterpret_cast<const unsigned char*>(default_val));
default:
return MB_TAG_NOT_FOUND;
}
@@ -543,11 +504,9 @@
case MB_TAG_SPARSE:
return mSparseData->get_data( tag_id, entity_handles, data, default_val );
case MB_TAG_BIT:
- if (entity_handles.size() == 1)
- return get_bits( tag_handle, entity_handles.front(), *reinterpret_cast<unsigned char*>(data) );
- else
- return MB_FAILURE;
-
+ return mBitServer->get_bits( tag_id, entity_handles,
+ reinterpret_cast<unsigned char*>(data),
+ reinterpret_cast<const unsigned char*>(default_val));
default:
return MB_TAG_NOT_FOUND;
}
@@ -572,11 +531,7 @@
case MB_TAG_SPARSE:
return mSparseData->get_data( tag_id, entity_handles, num_entities, data, lengths, default_val, def_val_len );
case MB_TAG_BIT:
- if (num_entities == 1)
- return get_bits( tag_handle, *entity_handles, *reinterpret_cast<unsigned char*>(data) );
- else
- return MB_FAILURE;
-
+ return MB_FAILURE;
default:
return MB_TAG_NOT_FOUND;
}
@@ -600,11 +555,7 @@
case MB_TAG_SPARSE:
return mSparseData->get_data( tag_id, entity_handles, data, lengths, default_val, def_val_len );
case MB_TAG_BIT:
- if (entity_handles.size() == 1)
- return get_bits( tag_handle, entity_handles.front(), *reinterpret_cast<unsigned char*>(data) );
- else
- return MB_FAILURE;
-
+ return MB_FAILURE;
default:
return MB_TAG_NOT_FOUND;
}
Modified: MOAB/trunk/TagServer.hpp
===================================================================
--- MOAB/trunk/TagServer.hpp 2009-11-20 17:58:25 UTC (rev 3378)
+++ MOAB/trunk/TagServer.hpp 2009-11-20 19:00:50 UTC (rev 3379)
@@ -222,13 +222,7 @@
const MBRange& entity_handles,
const void** data,
int* lengths = 0 );
-
- //! set the value of a tag
- MBErrorCode set_bits(const MBTag tag_handle, const MBEntityHandle entity_handle, unsigned char data );
- //! get the value of a tag
- MBErrorCode get_bits(const MBTag tag_handle, const MBEntityHandle entity_handle, unsigned char& data );
-
//! remove global/mesh value of tag
MBErrorCode remove_mesh_data( const MBTag tag_handle );
Modified: MOAB/trunk/WriteHDF5.cpp
===================================================================
--- MOAB/trunk/WriteHDF5.cpp 2009-11-20 17:58:25 UTC (rev 3378)
+++ MOAB/trunk/WriteHDF5.cpp 2009-11-20 19:00:50 UTC (rev 3379)
@@ -1845,20 +1845,7 @@
iter = stop;
assert(range.size() == (unsigned)count);
- /** Fix me - stupid API requires we get these one at a time for BIT tags */
- if (mb_type == MB_TAG_BIT)
- {
- rval = MB_SUCCESS;
- char* buf_iter = tag_buffer;
- for (MBRange::const_iterator it = range.begin();
- MB_SUCCESS == rval && it != range.end();
- ++it, buf_iter += mb_size)
- rval = iFace->tag_get_data( tag_data.tag_id, &*it, 1, buf_iter );
- }
- else
- {
- rval = iFace->tag_get_data( tag_data.tag_id, range, tag_buffer );
- }
+ rval = iFace->tag_get_data( tag_data.tag_id, range, tag_buffer );
if (MB_SUCCESS != rval) {
mhdf_closeData( filePtr, tables[1], &status );
if (value_type && value_type != id_type)
1
0
Author: kraftche
Date: 2009-11-20 11:58:25 -0600 (Fri, 20 Nov 2009)
New Revision: 3378
Modified:
MOAB/trunk/tools/iMesh/Makefile.am
MOAB/trunk/tools/iMesh/iMesh-Defs.inc.in
Log:
remove extra include directory from installed iMesh-Defs.inc
Modified: MOAB/trunk/tools/iMesh/Makefile.am
===================================================================
--- MOAB/trunk/tools/iMesh/Makefile.am 2009-11-20 17:39:29 UTC (rev 3377)
+++ MOAB/trunk/tools/iMesh/Makefile.am 2009-11-20 17:58:25 UTC (rev 3378)
@@ -79,6 +79,7 @@
install-data-hook:
echo "IMESH_DIR=${cfgdir}/.." >> $(DESTDIR)$(cfgdir)/iMesh-SIDL-Defs.inc
echo "IMESH_INCLUDEDIR=${includedir}" >> $(DESTDIR)$(cfgdir)/iMesh-Defs.inc
+ echo "IMESH_INCLUDEDIR2=" >> $(DESTDIR)$(cfgdir)/iMesh-Defs.inc
echo "IMESH_LIBDIR=${libdir}" >> $(DESTDIR)$(cfgdir)/iMesh-Defs.inc
echo "MOAB_LIBDIR=${libdir}" >> $(DESTDIR)$(cfgdir)/iMesh-Defs.inc
Modified: MOAB/trunk/tools/iMesh/iMesh-Defs.inc.in
===================================================================
--- MOAB/trunk/tools/iMesh/iMesh-Defs.inc.in 2009-11-20 17:39:29 UTC (rev 3377)
+++ MOAB/trunk/tools/iMesh/iMesh-Defs.inc.in 2009-11-20 17:58:25 UTC (rev 3378)
@@ -9,7 +9,7 @@
IMESH_FCDEFS = @DEFS@
-IMESH_INCLUDES = -I$(IMESH_INCLUDEDIR) -I@abs_top_builddir@
+IMESH_INCLUDES = -I$(IMESH_INCLUDEDIR) $(IMESH_INCLUDEDIR2)
IMESH_LIBS = $(IMESH_LDFLAGS) -L$(MOAB_LIBDIR) \
-L$(IMESH_LIBDIR) -liMesh -lMOAB \
@@ -17,6 +17,7 @@
$(IMESH_CXX_LDFLAGS) $(IMESH_CXX_LIBS) \
@CGM_LDFLAGS@ @CGM_LIBS@
-IMESH_INCLUDEDIR = @abs_srcdir@
+IMESH_INCLUDEDIR1 = @abs_srcdir@
+IMESH_INCLUDEDIR2 = -I@abs_top_builddir@
IMESH_LIBDIR = @abs_builddir@/.libs
MOAB_LIBDIR = @abs_builddir@/../../.libs
1
0