From c5f0e3b75cdef3458fa5df9599947a3472034730 Mon Sep 17 00:00:00 2001 From: Cody Permann Date: Tue, 27 Aug 2013 15:22:21 -0600 Subject: [PATCH] Adding a configurable "unique_id" to DofObject. Currently works for SerialMesh and ParallelMesh --- configure | 87 ++++++++++++++++++++++ include/base/dof_object.h | 70 +++++++++++++++++ include/base/id_types.h | 21 +++++- include/libmesh_config.h.in | 6 ++ include/mesh/mesh_base.h | 16 +++- include/mesh/parallel_mesh.h | 8 ++ include/mesh/serial_mesh.h | 9 +++ include/parallel/parallel_implementation.h | 1 + m4/config_summary.m4 | 4 + m4/libmesh_core_features.m4 | 59 +++++++++++++++ src/base/dof_object.C | 1 + src/mesh/mesh_base.C | 14 ++++ src/mesh/parallel_mesh.C | 38 ++++++++++ src/mesh/serial_mesh.C | 35 +++++++-- src/parallel/parallel_elem.C | 34 +++++++-- src/parallel/parallel_node.C | 19 +++++ 16 files changed, 407 insertions(+), 15 deletions(-) diff --git a/configure b/configure index 358db89bee4..c0cec9f851e 100755 --- a/configure +++ b/configure @@ -1062,6 +1062,8 @@ with_dof_id_bytes with_processor_id_bytes with_subdomain_id_bytes enable_everything +enable_unique_id +with_unique_id_bytes enable_tracefiles enable_amr enable_vsmoother @@ -1827,6 +1829,7 @@ Optional Features: --enable-legacy-using-namespace add "using namespace libMesh" to libMesh headers --enable-everything treat all applicable options as enabled + --enable-unique-id build with unique id suppport --enable-tracefiles write stack trace files on unexpected errors --enable-amr build with adaptive mesh refinement (AMR) suppport --enable-vsmoother build with variational smoother suppport @@ -1911,6 +1914,8 @@ Optional Packages: --with-subdomain-id-bytes=<1|2|4|8> bytes of storage per element used to store the subdomain_id + --with-unique-id-bytes=<1|2|4|8> + bytes used per unique id --with-boost[=ARG] use Boost library from a standard location (ARG=yes), from the specified location (ARG=), or disable it (ARG=no) [ARG=yes] @@ -26717,6 +26722,84 @@ fi + +# ------------------------------------------------------------- +# unique_id -- disable by default +# ------------------------------------------------------------- +# Check whether --enable-unique-id was given. +if test "${enable_unique_id+set}" = set; then : + enableval=$enable_unique_id; case "${enableval}" in + yes) enableuniqueid=yes ;; + no) enableuniqueid=no ;; + *) as_fn_error $? "bad value ${enableval} for --enable-unique-id" "$LINENO" 5 ;; + esac +else + enableuniqueid=$enableeverything +fi + + +if test "$enableuniqueid" = yes ; then + +$as_echo "#define ENABLE_UNIQUE_ID 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: <<< Configuring library with unique id support >>>" >&5 +$as_echo "<<< Configuring library with unique id support >>>" >&6; } +fi +# ------------------------------------------------------------- + + + +# ------------------------------------------------------------- +# size of unique_id_type -- default 8 bytes +# ------------------------------------------------------------- + +# Check whether --with-unique_id_bytes was given. +if test "${with_unique_id_bytes+set}" = set; then : + withval=$with_unique_id_bytes; unique_bytes="$withval" +else + unique_bytes=8 +fi + + +case "$unique_bytes" in + 1) + +$as_echo "#define UNIQUE_ID_BYTES 1" >>confdefs.h + + ;; + 2) + +$as_echo "#define UNIQUE_ID_BYTES 2" >>confdefs.h + + ;; + 4) + +$as_echo "#define UNIQUE_ID_BYTES 4" >>confdefs.h + + ;; + 8) + +$as_echo "#define UNIQUE_ID_BYTES 8" >>confdefs.h + + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: >>> unrecognized unique_id size: $unique_bytes - configuring size...8" >&5 +$as_echo ">>> unrecognized unique_id size: $unique_bytes - configuring size...8" >&6; } + +$as_echo "#define UNIQUE_ID_BYTES 8" >>confdefs.h + + unique_bytes=8 + ;; +esac + +if test "$enableuniqueid" = yes ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: configuring size of unique_id... $unique_bytes" >&5 +$as_echo "configuring size of unique_id... $unique_bytes" >&6; } +fi +# ------------------------------------------------------------- + + + # -------------------------------------------------------------- # Write stack trace output files on error() - disabled by default # -------------------------------------------------------------- @@ -37572,8 +37655,12 @@ echo ' complex variables................ :' $enablecomplex echo ' example suite.................... :' $enableexamples echo ' ghosted vectors.................. :' $enableghosted echo ' high-order shape functions....... :' $enablepfem +echo ' unique-id support................ :' $enableuniqueid echo ' id size (boundaries)............. :' $boundary_bytes bytes echo ' id size (dofs)................... :' $dof_bytes bytes +if (test "x$enableuniqueid" = "xyes"); then +echo ' id size (unique)................. :' $unique_bytes bytes +fi echo ' id size (processors)............. :' $processor_bytes bytes echo ' id size (subdomains)............. :' $subdomain_bytes bytes echo ' infinite elements................ :' $enableifem diff --git a/include/base/dof_object.h b/include/base/dof_object.h index 89e66936e09..d1b23865968 100644 --- a/include/base/dof_object.h +++ b/include/base/dof_object.h @@ -145,6 +145,16 @@ class DofObject : public ReferenceCountedObject */ dof_id_type & set_id (); + /** + * \returns the globally \p unique_id for this \p DofObject + */ + unique_id_type unique_id () const; + + /** + * \returns the globally \p unique_id for this \p DofObject as a writeable reference. + */ + unique_id_type & set_unique_id (); + /** * Sets the \p id for this \p DofObject */ @@ -157,6 +167,12 @@ class DofObject : public ReferenceCountedObject */ bool valid_id () const; + /** + * @returns \p true if this \p DofObject has a valid \p unique_id set, + * \p false otherwise. + */ + bool valid_unique_id () const; + /** * @returns the processor that this DofObject belongs to. * @@ -318,6 +334,11 @@ class DofObject : public ReferenceCountedObject */ static const dof_id_type invalid_id = static_cast(-1); + /** + * An invaild \p unique_id to distinguish an uninitialized \p DofObject + */ + static const unique_id_type invalid_unique_id = static_cast(-1); + /** * An invalid \p processor_id to distinguish DoFs that have * not been assigned to a processor. @@ -378,6 +399,14 @@ class DofObject : public ReferenceCountedObject */ dof_id_type _id; + + /** + * A globally unique id, guarenteed not to change as the mesh is repartioned or adapted + */ +#ifdef LIBMESH_ENABLE_UNIQUE_ID + unique_id_type _unique_id; +#endif + /** * The \p processor_id of the \p DofObject. * Degrees of freedom are wholly owned by processors, @@ -474,6 +503,9 @@ DofObject::DofObject () : old_dof_object(NULL), #endif _id (invalid_id), +#ifdef LIBMESH_ENABLE_UNIQUE_ID + _unique_id (invalid_unique_id), +#endif _processor_id (invalid_processor_id) { this->invalidate(); @@ -592,6 +624,31 @@ dof_id_type & DofObject::set_id () +inline +unique_id_type DofObject::unique_id () const +{ +#ifdef LIBMESH_ENABLE_UNIQUE_ID + libmesh_assert (this->valid_unique_id()); + return _unique_id; +#else + return invalid_unique_id; +#endif +} + + + +inline +unique_id_type & DofObject::set_unique_id () +{ +#ifdef LIBMESH_ENABLE_UNIQUE_ID + return _unique_id; +#else + libmesh_error(); +#endif +} + + + inline bool DofObject::valid_id () const { @@ -599,6 +656,19 @@ bool DofObject::valid_id () const } + +inline +bool DofObject::valid_unique_id () const +{ +#ifdef LIBMESH_ENABLE_UNIQUE_ID + return (DofObject::invalid_unique_id != _unique_id); +#else + return false; +#endif +} + + + inline processor_id_type DofObject::processor_id () const { diff --git a/include/base/id_types.h b/include/base/id_types.h index c9766df540d..5fc661d4a70 100644 --- a/include/base/id_types.h +++ b/include/base/id_types.h @@ -65,6 +65,18 @@ typedef uint32_t dof_id_type; #endif +#if LIBMESH_UNIQUE_ID_BYTES == 1 +typedef uint8_t unique_id_type; +#elif LIBMESH_UNIQUE_ID_BYTES == 2 +typedef uint16_t unique_id_type; +#elif LIBMESH_UNIQUE_ID_BYTES == 4 +typedef uint32_t unique_id_type; +#else // LIBMESH_UNIQUE_ID_BYTES == 8 (default) +typedef uint64_t unique_id_type; + +#endif + + // We may want to specialize this later, but for now we'll assume // numeric vector indices are the same as dof indices typedef dof_id_type numeric_index_type; @@ -104,13 +116,16 @@ typedef uint16_t subdomain_id_type; #endif #if (LIBMESH_BOUNDARY_ID_BYTES > 4) || (LIBMESH_DOF_ID_BYTES > 4) || \ - (LIBMESH_PROCESSOR_ID_BYTES > 4) || (LIBMESH_SUBDOMAIN_ID_BYTES > 4) + (LIBMESH_UNIQUE_ID_BYTES > 4) || (LIBMESH_PROCESSOR_ID_BYTES > 4) || \ + (LIBMESH_SUBDOMAIN_ID_BYTES > 4) typedef uint64_t largest_id_type; #elif (LIBMESH_BOUNDARY_ID_BYTES > 2) || (LIBMESH_DOF_ID_BYTES > 2) || \ - (LIBMESH_PROCESSOR_ID_BYTES > 2) || (LIBMESH_SUBDOMAIN_ID_BYTES > 2) + (LIBMESH_UNIQUE_ID_BYTES > 2) || (LIBMESH_PROCESSOR_ID_BYTES > 2) || \ + (LIBMESH_SUBDOMAIN_ID_BYTES > 2) typedef uint32_t largest_id_type; #elif (LIBMESH_BOUNDARY_ID_BYTES > 1) || (LIBMESH_DOF_ID_BYTES > 1) || \ - (LIBMESH_PROCESSOR_ID_BYTES > 1) || (LIBMESH_SUBDOMAIN_ID_BYTES > 1) + (LIBMESH_UNIQUE_ID_BYTES > 1) || (LIBMESH_PROCESSOR_ID_BYTES > 1) || \ + (LIBMESH_SUBDOMAIN_ID_BYTES > 1) typedef uint16_t largest_id_type; #else typedef uint8_t largest_id_type; diff --git a/include/libmesh_config.h.in b/include/libmesh_config.h.in index 9c6e451ddc4..ca836ecd0ef 100644 --- a/include/libmesh_config.h.in +++ b/include/libmesh_config.h.in @@ -142,6 +142,9 @@ on unexpected errors */ #undef ENABLE_TRACEFILES +/* Flag indicating if the library should be built with unique id support */ +#undef ENABLE_UNIQUE_ID + /* Flag indicating if the library should be built with variational smoother support */ #undef ENABLE_VSMOOTHER @@ -509,6 +512,9 @@ /* If the compiler supports a TLS storage class define it to that here */ #undef TLS +/* size of unique_id */ +#undef UNIQUE_ID_BYTES + /* Flag indicating if the library should be built using complxex numbers */ #undef USE_COMPLEX_NUMBERS diff --git a/include/mesh/mesh_base.h b/include/mesh/mesh_base.h index ac7b58e070b..00f815ffdcd 100644 --- a/include/mesh/mesh_base.h +++ b/include/mesh/mesh_base.h @@ -822,8 +822,13 @@ class MeshBase : public ParallelObject protected: - - + /** + * Assign globally unique IDs to all DOF objects (Elements and Nodes) + * if the library has been configured with unique_id support. + */ +#ifdef LIBMESH_ENABLE_UNIQUE_ID + virtual void assign_unique_ids() = 0; +#endif /** * Returns a writeable reference to the number of partitions. @@ -869,6 +874,13 @@ class MeshBase : public ParallelObject */ AutoPtr _partitioner; +#ifdef LIBMESH_ENABLE_UNIQUE_ID + /** + * The next available unique id for assigning ids to DOF objects + */ + unique_id_type _next_unique_id; +#endif + /** * If this is true then no partitioning should be done. */ diff --git a/include/mesh/parallel_mesh.h b/include/mesh/parallel_mesh.h index d69d7addbf0..c6048ca420d 100644 --- a/include/mesh/parallel_mesh.h +++ b/include/mesh/parallel_mesh.h @@ -409,6 +409,14 @@ class ParallelMesh : public UnstructuredMesh protected: + /** + * Assign globally unique IDs to all DOF objects (Elements and Nodes) + * if the library has been configured with unique_id support. + */ +#ifdef LIBMESH_ENABLE_UNIQUE_ID + virtual void assign_unique_ids(); +#endif + /** * The verices (spatial coordinates) of the mesh. */ diff --git a/include/mesh/serial_mesh.h b/include/mesh/serial_mesh.h index 736baa81cec..ded581b3848 100644 --- a/include/mesh/serial_mesh.h +++ b/include/mesh/serial_mesh.h @@ -375,6 +375,15 @@ class SerialMesh : public UnstructuredMesh const_node_iterator pid_nodes_end (const processor_id_type proc_id) const; protected: + +#ifdef LIBMESH_ENABLE_UNIQUE_ID + /** + * Assign globally unique IDs to all DOF objects (Elements and Nodes) + * if the library has been configured with unique_id support. + */ + virtual void assign_unique_ids(); +#endif + /** * The verices (spatial coordinates) of the mesh. */ diff --git a/include/parallel/parallel_implementation.h b/include/parallel/parallel_implementation.h index f02cf2c4190..e2f90a77314 100644 --- a/include/parallel/parallel_implementation.h +++ b/include/parallel/parallel_implementation.h @@ -104,6 +104,7 @@ INT_TYPE(int,MPI_INT); INT_TYPE(unsigned int,MPI_UNSIGNED); INT_TYPE(long,MPI_LONG); INT_TYPE(unsigned long,MPI_UNSIGNED_LONG); +INT_TYPE(unsigned long long,MPI_LONG_LONG_INT); FLOAT_TYPE(float,MPI_FLOAT); FLOAT_TYPE(double,MPI_DOUBLE); FLOAT_TYPE(long double,MPI_LONG_DOUBLE); diff --git a/m4/config_summary.m4 b/m4/config_summary.m4 index ecdaa633d86..f954397b1e4 100644 --- a/m4/config_summary.m4 +++ b/m4/config_summary.m4 @@ -72,8 +72,12 @@ echo ' complex variables................ :' $enablecomplex echo ' example suite.................... :' $enableexamples echo ' ghosted vectors.................. :' $enableghosted echo ' high-order shape functions....... :' $enablepfem +echo ' unique-id support................ :' $enableuniqueid echo ' id size (boundaries)............. :' $boundary_bytes bytes echo ' id size (dofs)................... :' $dof_bytes bytes +if (test "x$enableuniqueid" = "xyes"); then +echo ' id size (unique)................. :' $unique_bytes bytes +fi echo ' id size (processors)............. :' $processor_bytes bytes echo ' id size (subdomains)............. :' $subdomain_bytes bytes echo ' infinite elements................ :' $enableifem diff --git a/m4/libmesh_core_features.m4 b/m4/libmesh_core_features.m4 index b2168de3be9..f9badb158c1 100644 --- a/m4/libmesh_core_features.m4 +++ b/m4/libmesh_core_features.m4 @@ -234,6 +234,65 @@ AC_ARG_ENABLE(everything, enableeverything=no) + +# ------------------------------------------------------------- +# unique_id -- disable by default +# ------------------------------------------------------------- +AC_ARG_ENABLE(unique-id, + AC_HELP_STRING([--enable-unique-id], + [build with unique id suppport]), + [case "${enableval}" in + yes) enableuniqueid=yes ;; + no) enableuniqueid=no ;; + *) AC_MSG_ERROR(bad value ${enableval} for --enable-unique-id) ;; + esac], + [enableuniqueid=$enableeverything]) + +if test "$enableuniqueid" = yes ; then + AC_DEFINE(ENABLE_UNIQUE_ID, 1, + [Flag indicating if the library should be built with unique id support]) + AC_MSG_RESULT(<<< Configuring library with unique id support >>>) +fi +# ------------------------------------------------------------- + + + +# ------------------------------------------------------------- +# size of unique_id_type -- default 8 bytes +# ------------------------------------------------------------- +AC_ARG_WITH([unique_id_bytes], + AC_HELP_STRING([--with-unique-id-bytes=<1|2|4|8>], + [bytes used per unique id]), + [unique_bytes="$withval"], + [unique_bytes=8]) + +case "$unique_bytes" in + 1) + AC_DEFINE(UNIQUE_ID_BYTES, 1, [size of unique_id]) + ;; + 2) + AC_DEFINE(UNIQUE_ID_BYTES, 2, [size of unique_id]) + ;; + 4) + AC_DEFINE(UNIQUE_ID_BYTES, 4, [size of unique_id]) + ;; + 8) + AC_DEFINE(UNIQUE_ID_BYTES, 8, [size of unique_id]) + ;; + *) + AC_MSG_RESULT([>>> unrecognized unique_id size: $unique_bytes - configuring size...8]) + AC_DEFINE(UNIQUE_ID_BYTES, 8, [size of unique_id]) + unique_bytes=8 + ;; +esac + +if test "$enableuniqueid" = yes ; then + AC_MSG_RESULT([configuring size of unique_id... $unique_bytes]) +fi +# ------------------------------------------------------------- + + + # -------------------------------------------------------------- # Write stack trace output files on error() - disabled by default # -------------------------------------------------------------- diff --git a/src/base/dof_object.C b/src/base/dof_object.C index d292c04b791..f3d67d73189 100644 --- a/src/base/dof_object.C +++ b/src/base/dof_object.C @@ -31,6 +31,7 @@ namespace libMesh // ------------------------------------------------------------ // DofObject class static member -now initialized in header const dof_id_type DofObject::invalid_id; +const unique_id_type DofObject::invalid_unique_id; const processor_id_type DofObject::invalid_processor_id; diff --git a/src/mesh/mesh_base.C b/src/mesh/mesh_base.C index 98b086d672b..77c09a5ad4c 100644 --- a/src/mesh/mesh_base.C +++ b/src/mesh/mesh_base.C @@ -52,6 +52,9 @@ MeshBase::MeshBase (const Parallel::Communicator &comm, _is_prepared (false), _point_locator (NULL), _partitioner (NULL), +#ifdef LIBMESH_ENABLE_UNIQUE_ID + _next_unique_id(DofObject::invalid_unique_id), +#endif _skip_partitioning(false), _skip_renumber_nodes_and_elements(false) { @@ -70,6 +73,9 @@ MeshBase::MeshBase (unsigned int d) : _is_prepared (false), _point_locator (NULL), _partitioner (NULL), +#ifdef LIBMESH_ENABLE_UNIQUE_ID + _next_unique_id(DofObject::invalid_unique_id), +#endif _skip_partitioning(false), _skip_renumber_nodes_and_elements(false) { @@ -89,6 +95,9 @@ MeshBase::MeshBase (const MeshBase& other_mesh) : _is_prepared (other_mesh._is_prepared), _point_locator (NULL), _partitioner (NULL), +#ifdef LIBMESH_ENABLE_UNIQUE_ID + _next_unique_id(other_mesh._next_unique_id), +#endif _skip_partitioning(other_mesh._skip_partitioning), _skip_renumber_nodes_and_elements(false) { @@ -163,6 +172,11 @@ void MeshBase::prepare_for_use (const bool skip_renumber_nodes_and_elements) if(!_skip_renumber_nodes_and_elements) this->renumber_nodes_and_elements(); +#ifdef LIBMESH_ENABLE_UNIQUE_ID + // Assign DOF object unique ids + this->assign_unique_ids(); +#endif + // Reset our PointLocator. This needs to happen any time the elements // in the underlying elements in the mesh have changed, so we do it here. this->clear_point_locator(); diff --git a/src/mesh/parallel_mesh.C b/src/mesh/parallel_mesh.C index e0112f02aa0..72469720298 100644 --- a/src/mesh/parallel_mesh.C +++ b/src/mesh/parallel_mesh.C @@ -40,6 +40,10 @@ ParallelMesh::ParallelMesh (const Parallel::Communicator &comm, _next_free_unpartitioned_node_id(this->n_processors()), _next_free_unpartitioned_elem_id(this->n_processors()) { +#ifdef LIBMESH_ENABLE_UNIQUE_ID + _next_unique_id = this->processor_id(); +#endif + // FIXME: give parmetis the communicator! _partitioner = AutoPtr(new ParmetisPartitioner()); } @@ -56,6 +60,10 @@ ParallelMesh::ParallelMesh (unsigned int d) : _next_free_unpartitioned_node_id(this->n_processors()), _next_free_unpartitioned_elem_id(this->n_processors()) { +#ifdef LIBMESH_ENABLE_UNIQUE_ID + _next_unique_id = this->processor_id(); +#endif + // FIXME: give parmetis the communicator! _partitioner = AutoPtr(new ParmetisPartitioner()); } @@ -1275,4 +1283,34 @@ void ParallelMesh::allgather() #endif } +#ifdef LIBMESH_ENABLE_UNIQUE_ID +void ParallelMesh::assign_unique_ids() +{ + { + elem_iterator_imp it = _elements.begin(); + const elem_iterator_imp end = _elements.end(); + + for (; it != end; ++it) + if ((*it) && ! (*it)->valid_unique_id() && libMesh::processor_id() == (*it)->processor_id()) + { + (*it)->set_unique_id() = _next_unique_id; + _next_unique_id += this->n_processors(); + } + } + + { + node_iterator_imp it = _nodes.begin(); + node_iterator_imp end = _nodes.end(); + + for (; it != end; ++it) + if ((*it) && ! (*it)->valid_unique_id() && libMesh::processor_id() == (*it)->processor_id()) + { + (*it)->set_unique_id() = _next_unique_id; + _next_unique_id += this->n_processors(); + } + } +} +#endif + + } // namespace libMesh diff --git a/src/mesh/serial_mesh.C b/src/mesh/serial_mesh.C index a1e3188c259..8dd042c3967 100644 --- a/src/mesh/serial_mesh.C +++ b/src/mesh/serial_mesh.C @@ -118,6 +118,11 @@ SerialMesh::SerialMesh (const Parallel::Communicator &comm, unsigned int d) : UnstructuredMesh (comm,d) { +#ifdef LIBMESH_ENABLE_UNIQUE_ID + // In serial we just need to reset the next unique id to zero + // here in the constructor. + _next_unique_id = 0; +#endif _partitioner = AutoPtr(new MetisPartitioner()); } @@ -127,6 +132,11 @@ SerialMesh::SerialMesh (const Parallel::Communicator &comm, SerialMesh::SerialMesh (unsigned int d) : UnstructuredMesh (d) { +#ifdef LIBMESH_ENABLE_UNIQUE_ID + // In serial we just need to reset the next unique id to zero + // here in the constructor. + _next_unique_id = 0; +#endif _partitioner = AutoPtr(new MetisPartitioner()); } #endif @@ -804,7 +814,7 @@ void SerialMesh::stitching_helper (SerialMesh* other_mesh, boundary_id_type id_array[2] = {this_mesh_boundary_id, other_mesh_boundary_id}; std::set* set_array[2] = {&this_boundary_node_ids, &other_boundary_node_ids}; SerialMesh* mesh_array[2] = {this, other_mesh}; - + for (unsigned i=0; i<2; ++i) { MeshBase::element_iterator elem_it = mesh_array[i]->elements_begin(); @@ -836,14 +846,14 @@ void SerialMesh::stitching_helper (SerialMesh* other_mesh, if (verbose) { libMesh::out << "In SerialMesh::stitch_meshes:\n" - << "This mesh has " << this_boundary_node_ids.size() + << "This mesh has " << this_boundary_node_ids.size() << " nodes on boundary " << this_mesh_boundary_id << ".\n" << "Other mesh has " << other_boundary_node_ids.size() << " nodes on boundary " << other_mesh_boundary_id << ".\n" << "Minimum edge length on both surfaces is " << h_min << ".\n" << std::endl; } - + if(use_binary_search) { @@ -1000,7 +1010,7 @@ void SerialMesh::stitching_helper (SerialMesh* other_mesh, << " matching nodes.\n" << std::endl; } - + if(enforce_all_nodes_match_on_boundaries) { unsigned int n_matching_nodes = node_to_node_map.size(); @@ -1105,7 +1115,7 @@ void SerialMesh::stitching_helper (SerialMesh* other_mesh, // Then decrement dof_id_type new_id = el->id() - elem_delta; el->set_id(new_id); - } + } } // end if(other_mesh) // Finally, we need to "merge" the overlapping nodes @@ -1180,4 +1190,19 @@ dof_id_type SerialMesh::n_active_elem () const this->active_elements_end())); } + +#ifdef LIBMESH_ENABLE_UNIQUE_ID +void SerialMesh::assign_unique_ids() +{ + for (dof_id_type i=0; i<_elements.size(); ++i) + if (_elements[i] && ! _elements[i]->valid_unique_id()) + _elements[i]->set_unique_id() = _next_unique_id++; + + for (dof_id_type i=0; i<_nodes.size(); ++i) + if (_nodes[i] && ! _nodes[i]->valid_unique_id()) + _nodes[i]->set_unique_id() = _next_unique_id++; +} +#endif + + } // namespace libMesh diff --git a/src/parallel/parallel_elem.C b/src/parallel/parallel_elem.C index 888e3992a49..cc2b3e944c8 100644 --- a/src/parallel/parallel_elem.C +++ b/src/parallel/parallel_elem.C @@ -31,7 +31,11 @@ namespace { +#ifdef LIBMESH_ENABLE_UNIQUE_ID + static const unsigned int header_size = 11; +#else static const unsigned int header_size = 10; +#endif static const largest_id_type elem_magic_header = 987654321; } @@ -168,6 +172,14 @@ void pack (const Elem* elem, data.push_back (elem->subdomain_id()); data.push_back (elem->id()); +#ifdef LIBMESH_ENABLE_UNIQUE_ID + if (elem->valid_unique_id()) + data.push_back (static_cast(elem->unique_id())); + else + // OK to send invalid unique id, we must not own this DOF + data.push_back (static_cast(DofObject::invalid_unique_id)); +#endif + #ifdef LIBMESH_ENABLE_AMR // use parent_ID of -1 to indicate a level 0 element if (elem->level() == 0) @@ -302,14 +314,20 @@ void unpack(std::vector::const_iterator in, static_cast(*in++); libmesh_assert_not_equal_to (id, DofObject::invalid_id); +#ifdef LIBMESH_ENABLE_UNIQUE_ID + // int 8: dof object unique id + const unique_id_type unique_id = + static_cast(*in++); +#endif + #ifdef LIBMESH_ENABLE_AMR - // int 8: parent dof object id + // int 9: parent dof object id const dof_id_type parent_id = static_cast(*in++); libmesh_assert (level == 0 || parent_id != DofObject::invalid_id); libmesh_assert (level != 0 || parent_id == DofObject::invalid_id); - // int 9: local child id + // int 10: local child id const unsigned int which_child_am_i = static_cast(*in++); #else @@ -329,6 +347,9 @@ void unpack(std::vector::const_iterator in, { libmesh_assert_equal_to (elem->level(), level); libmesh_assert_equal_to (elem->id(), id); +//#ifdef LIBMESH_ENABLE_UNIQUE_ID + // No check for unqiue id sanity +//#endif libmesh_assert_equal_to (elem->processor_id(), processor_id); libmesh_assert_equal_to (elem->subdomain_id(), subdomain_id); libmesh_assert_equal_to (elem->type(), type); @@ -463,9 +484,12 @@ void unpack(std::vector::const_iterator in, #endif // LIBMESH_ENABLE_AMR // Assign the IDs - elem->subdomain_id() = subdomain_id; - elem->processor_id() = processor_id; - elem->set_id() = id; + elem->subdomain_id() = subdomain_id; + elem->processor_id() = processor_id; + elem->set_id() = id; +#ifdef LIBMESH_ENABLE_UNIQUE_ID + elem->set_unique_id() = unique_id; +#endif // Assign the connectivity libmesh_assert_equal_to (elem->n_nodes(), n_nodes); diff --git a/src/parallel/parallel_node.C b/src/parallel/parallel_node.C index a9236a73ab6..6f12147bb62 100644 --- a/src/parallel/parallel_node.C +++ b/src/parallel/parallel_node.C @@ -32,7 +32,11 @@ namespace { using namespace libMesh; +#ifdef LIBMESH_ENABLE_UNIQUE_ID + static const unsigned int header_size = 3; +#else static const unsigned int header_size = 2; +#endif // use "(a+b-1)/b" trick to get a/b to round up static const unsigned int idtypes_per_Real = @@ -120,6 +124,14 @@ void pack (const Node* node, data.push_back (static_cast(node->processor_id())); data.push_back (static_cast(node->id())); +#ifdef LIBMESH_ENABLE_UNIQUE_ID + if (node->valid_unique_id()) + data.push_back (static_cast(node->unique_id())); + else + // OK to send invalid unique id, we must not own this DOF + data.push_back (static_cast(DofObject::invalid_unique_id)); +#endif + // use "(a+b-1)/b" trick to get a/b to round up static const unsigned int idtypes_per_Real = (sizeof(Real) + sizeof(largest_id_type) - 1) / sizeof(largest_id_type); @@ -188,6 +200,10 @@ void unpack (std::vector::const_iterator in, const dof_id_type id = static_cast(*in++); +#ifdef LIBMESH_ENABLE_UNIQUE_ID + const unique_id_type unique_id = static_cast(*in++); +#endif + Node *node = mesh->query_node_ptr(id); if (node) @@ -237,6 +253,9 @@ void unpack (std::vector::const_iterator in, } node->set_id() = id; +#ifdef LIBMESH_ENABLE_UNIQUE_ID + node->set_unique_id() = unique_id; +#endif node->processor_id() = processor_id; node->unpack_indexing(in);