On Tue, 23 Oct 2012, Kirk, Benjamin (JSC-EG311) wrote:

Let's find this Nemesis regression (has it been distilled? I could
help…),

Cory distilled it nicely a month ago; I've just been too swamped with
site visit stuff to get to it.

I'm cleaning up some other ParallelMesh stuff first (patch attached,
in case anyone wants to double check my --enable-parmesh
--enable-nodeconstraint fix) and should be able to get at it this
afternoon.

package the next release, and then get serious about
possible move…

This is sounding reasonable.  The centralization of a non-Distributed
VCS actually sounded like a nice thing to me right up until the point
where it became a central point of failure.
---
Roy
Index: include/base/dof_map.h
===================================================================
--- include/base/dof_map.h      (revision 6191)
+++ include/base/dof_map.h      (working copy)
@@ -503,7 +503,7 @@
   /**
    * Gathers constraint equation dependencies from other processors
    */
-  void allgather_recursive_constraints (const MeshBase&);
+  void allgather_recursive_constraints (MeshBase&);
 
   /**
    * Sends constraint equations to constraining processors
@@ -517,7 +517,7 @@
    * This should be run after both system (create_dof_constraints) and
    * user constraints have all been added.
    */
-  void process_constraints (const MeshBase&);
+  void process_constraints (MeshBase&);
 
   /**
    * Adds a copy of the user-defined row to the constraint matrix, using
Index: src/base/dof_map_constraints.C
===================================================================
--- src/base/dof_map_constraints.C      (revision 6191)
+++ src/base/dof_map_constraints.C      (working copy)
@@ -33,9 +33,11 @@
 #include "libmesh/libmesh_logging.h"
 #include "libmesh/system.h" // needed by enforce_constraints_exactly()
 #include "libmesh/mesh_base.h"
+#include "libmesh/mesh_inserter_iterator.h"
 #include "libmesh/numeric_vector.h" // for enforce_constraints_exactly()
 #include "libmesh/quadrature.h" // for dirichlet constraints
 #include "libmesh/parallel.h"
+#include "libmesh/parallel_algebra.h"
 #include "libmesh/periodic_boundaries.h"
 #include "libmesh/point_locator_base.h"
 #include "libmesh/threads.h"
@@ -1924,12 +1926,7 @@
 }
 
 
-// NodeConstraints can fail in parallel when we try to look up a node
-// that our processor doesn't have.  Until we have a fix for that,
-// let's just disable the allgather attempt.
-#undef LIBMESH_ENABLE_NODE_CONSTRAINTS
-
-void DofMap::allgather_recursive_constraints(const MeshBase&
+void DofMap::allgather_recursive_constraints(MeshBase&
 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
 mesh
 #endif
@@ -2176,6 +2173,9 @@
 
   while (unexpanded_set_nonempty)
     {
+      // Let's make sure we don't lose sync in this loop.
+      parallel_only();
+
       // Request sets
       DoF_RCSet   dof_request_set;
       Node_RCSet node_request_set;
@@ -2197,7 +2197,16 @@
           DofConstraintRow &row = _dof_constraints[*i].first;
           for (DofConstraintRow::iterator j = row.begin();
                j != row.end(); ++j)
-            dof_request_set.insert(j->first);
+            {
+              const unsigned int constraining_dof = j->first;
+
+              // If it's non-local and we haven't already got a
+              // constraint for it, we might need to ask for one
+              if (((constraining_dof < this->first_dof()) ||
+                   (constraining_dof >= this->end_dof())) &&
+                  !_dof_constraints.count(constraining_dof))
+                dof_request_set.insert(constraining_dof);
+            }
         }
 
 #ifdef LIBMESH_ENABLE_NODE_CONSTRAINTS
@@ -2208,8 +2217,14 @@
           for (NodeConstraintRow::iterator j = row.begin();
                j != row.end(); ++j)
             {
-              libmesh_assert(j->first);
-              node_request_set.insert(j->first);
+              const Node* const node = j->first;
+              libmesh_assert(node);
+
+              // If it's non-local and we haven't already got a
+              // constraint for it, we might need to ask for one
+              if ((node->processor_id() != libMesh::processor_id()) &&
+                  !_node_constraints.count(node))
+                node_request_set.insert(node);
             }
         }
 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
@@ -2278,6 +2293,11 @@
           // Fill those requests
           std::vector<std::vector<unsigned int> > 
dof_row_keys(dof_request_to_fill.size()),
                                                   
node_row_keys(node_request_to_fill.size());
+
+          // FIXME - this could be an unordered set, given a
+          // hash<pointers> specialization
+          std::set<const Node*> nodes_requested;
+
           std::vector<std::vector<Real> > 
dof_row_vals(dof_request_to_fill.size()),
                                           
node_row_vals(node_request_to_fill.size());
           std::vector<Number> dof_row_rhss(dof_request_to_fill.size());
@@ -2296,6 +2316,11 @@
                     {
                       dof_row_keys[i].push_back(j->first);
                       dof_row_vals[i].push_back(j->second);
+
+                      // We should never have a 0 constraint
+                      // coefficient; that's implicit via sparse
+                      // constraint storage
+                      libmesh_assert(j->second);
                     }
                   dof_row_rhss[i] = _dof_constraints[constrained].second;
                 }
@@ -2316,7 +2341,14 @@
                        j != row.end(); ++j)
                     {
                       node_row_keys[i].push_back(j->first->id());
+                      nodes_requested.insert(j->first);
                       node_row_vals[i].push_back(j->second);
+
+                      // We can have 0 nodal constraint
+                      // coefficients, where no Lagrange constrant
+                      // exists but non-Lagrange basis constraints
+                      // might.
+                      // libmesh_assert(j->second);
                     }
                   node_row_rhss[i] = 
_node_constraints[constrained_node].second;
                 }
@@ -2343,6 +2375,13 @@
                                  procup, node_filled_vals);
           Parallel::send_receive(procdown, node_row_rhss,
                                  procup, node_filled_rhss);
+
+          // Constraining nodes might not even exist on our subset of
+          // a distributed mesh, so let's make them exist.
+          Parallel::send_receive_packed_range
+            (procdown, &mesh, nodes_requested.begin(), nodes_requested.end(),
+             procup,   &mesh, mesh_inserter_iterator<Node>(mesh));
+
 #endif // LIBMESH_ENABLE_NODE_CONSTRAINTS
           libmesh_assert_equal_to (dof_filled_keys.size(), 
requested_dof_ids[procup].size());
           libmesh_assert_equal_to (dof_filled_vals.size(), 
requested_dof_ids[procup].size());
@@ -2404,7 +2443,7 @@
 
 
 
-void DofMap::process_constraints (const MeshBase& mesh)
+void DofMap::process_constraints (MeshBase& mesh)
 {
   // With a parallelized Mesh, we've computed our local constraints,
   // but they may depend on non-local constraints that we'll need to
------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_sfd2d_oct
_______________________________________________
Libmesh-devel mailing list
Libmesh-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libmesh-devel

Reply via email to