On Wed, 21 Jan 2009, Roy Stogner wrote:

I've found one of the bugs,

Great!

but don't know the best way to fix it.
With the attached patch, ex9 (at least) fails because the PetscVector
operator= is capable of taking a ghosted vector and producing a
non-ghosted vector copy with a non-empty global_to_local_map, which
then fails in operator() when VecGhostGetLocalForm is called on it.

I see. My idea is, since the vector is anyway cleared and re-initialized in operator=, why not use PETSc's VecDuplicate() function. This seems to fix ex9, see attached patch.

(Note on the patch: I did "svn diff > patch" as usual, which means that my patch includes your changes as well. You might find it easier to perform my changes manually, it's just replacing the contents of operator=. If you know some easy method to create incremental patches, please let me know.)

Best Regards,

Tim

--
Dr. Tim Kroeger
[email protected]            Phone +49-421-218-7710
[email protected]            Fax   +49-421-218-4236

Fraunhofer MEVIS, Institute for Medical Image Computing
Universitaetsallee 29, 28359 Bremen, Germany
Index: include/numerics/petsc_vector.h
===================================================================
--- include/numerics/petsc_vector.h     (Revision 3225)
+++ include/numerics/petsc_vector.h     (Arbeitskopie)
@@ -654,6 +654,13 @@
   int petsc_n=static_cast<int>(n);
   int petsc_n_local=static_cast<int>(n_local);
   int petsc_n_ghost=static_cast<int>(ghost.size());
+
+  // If the mesh is disjoint, the following assertion will fail.
+  // If the mesh is not disjoint, every processor will either have
+  // all the dofs, none of the dofs, or some non-zero dofs at the
+  // boundary between processors.
+  libmesh_assert(n_local == 0 || n_local == n || !ghost.empty());
+
   int* petsc_ghost = ghost.empty() ? PETSC_NULL :
     const_cast<int*>(reinterpret_cast<const int*>(&ghost[0]));
 
Index: include/base/dof_map.h
===================================================================
--- include/base/dof_map.h      (Revision 3225)
+++ include/base/dof_map.h      (Arbeitskopie)
@@ -582,7 +582,7 @@
    * when projecting the solution onto the refined mesh, hence the parent's
    * DOF indices need to be included in the \p _send_list.
    */
-  void augment_send_list_for_projection(const MeshBase &);
+  // void augment_send_list_for_projection(const MeshBase &);
 
   /**
    * Fills the vector di with the global degree of freedom indices
@@ -681,12 +681,9 @@
    * variable in the system.
    * Starts at index next_free_dof, and increments it to
    * the post-final index.
-   * If build_send_list is true, builds the send list.  If
-   * false, clears and reserves the send list
    */  
   void distribute_local_dofs_var_major (unsigned int& next_free_dof,
-                                       MeshBase& mesh,
-                                       const bool build_send_list);
+                                       MeshBase& mesh);
   
   /**
    * Distributes the global degrees of freedom, for dofs on
@@ -701,8 +698,7 @@
    * false, clears and reserves the send list
    */  
   void distribute_local_dofs_node_major (unsigned int& next_free_dof,
-                                        MeshBase& mesh,
-                                        const bool build_send_list);
+                                        MeshBase& mesh);
     
   /**
    * Adds entries to the \p _send_list vector corresponding to DoFs
Index: src/numerics/petsc_vector.C
===================================================================
--- src/numerics/petsc_vector.C (Revision 3225)
+++ src/numerics/petsc_vector.C (Arbeitskopie)
@@ -440,18 +440,18 @@
 {
   if (v.initialized())
     {
-      this->init (v.size(), v.local_size());
-      this->_global_to_local_map = v._global_to_local_map;
-      this->_is_closed      = v._is_closed;
-      this->_is_initialized = v._is_initialized;
-  
+      if (this->initialized())
+       this->clear();
       if (v.size() != 0)
        {
          int ierr = 0;
+         ierr = VecDuplicate (v._vec, &this->_vec);
+         CHKERRABORT(libMesh::COMM_WORLD,ierr);
+       }
 
-         ierr = VecCopy (v._vec, this->_vec);
-                        CHKERRABORT(libMesh::COMM_WORLD,ierr);
-       }
+      this->_global_to_local_map = v._global_to_local_map;
+      this->_is_closed      = v._is_closed;
+      this->_is_initialized = v._is_initialized;
     }
   
   return *this;
@@ -514,7 +514,7 @@
   PetscVector<T>* v_local = libmesh_cast_ptr<PetscVector<T>*>(&v_local_in);
 
   libmesh_assert (v_local != NULL);
-  libmesh_assert (v_local->local_size() == this->size());
+  libmesh_assert (v_local->size() == this->size());
 
   int ierr = 0;
   const int n = this->size();
@@ -573,19 +573,21 @@
   PetscVector<T>* v_local = libmesh_cast_ptr<PetscVector<T>*>(&v_local_in);
 
   libmesh_assert (v_local != NULL);
-  libmesh_assert (v_local->local_size() == this->size());
+  libmesh_assert (v_local->size() == this->size());
   libmesh_assert (send_list.size()     <= v_local->size());
   
   int ierr=0;
-  const int n_sl = send_list.size();
+  const unsigned int n_sl = send_list.size();
 
   IS is;
   VecScatter scatter;
 
-  std::vector<int> idx(n_sl);
+  std::vector<int> idx(n_sl + this->local_size());
   
-  for (int i=0; i<n_sl; i++)
+  for (unsigned int i=0; i<n_sl; i++)
     idx[i] = static_cast<int>(send_list[i]);
+  for (unsigned int i = 0; i != this->local_size(); ++i)
+    idx[n_sl+i] = i + this->first_local_index();
   
   // Create the index set & scatter object
   if (idx.empty())
Index: src/base/dof_map.C
===================================================================
--- src/base/dof_map.C  (Revision 3225)
+++ src/base/dof_map.C  (Arbeitskopie)
@@ -666,9 +666,9 @@
 
   // Set temporary DOF indices on this processor
   if (node_major_dofs)
-    this->distribute_local_dofs_node_major (next_free_dof, mesh, false);
+    this->distribute_local_dofs_node_major (next_free_dof, mesh);
   else
-    this->distribute_local_dofs_var_major (next_free_dof, mesh, false);
+    this->distribute_local_dofs_var_major (next_free_dof, mesh);
 
   // Get DOF counts on all processors
   std::vector<unsigned int> dofs_on_proc(n_proc, 0);
@@ -692,9 +692,9 @@
 
   // Set permanent DOF indices on this processor
   if (node_major_dofs)
-    this->distribute_local_dofs_node_major (next_free_dof, mesh, true);
+    this->distribute_local_dofs_node_major (next_free_dof, mesh);
   else
-    this->distribute_local_dofs_var_major (next_free_dof, mesh, true);
+    this->distribute_local_dofs_var_major (next_free_dof, mesh);
 
   libmesh_assert(next_free_dof == _end_df[proc_id]);
 
@@ -723,6 +723,8 @@
 
   STOP_LOG("distribute_dofs()", "DofMap");
 
+  _send_list.clear();
+
   // Note that in the add_neighbors_to_send_list nodes on processor
   // boundaries that are shared by multiple elements are added for
   // each element.
@@ -734,14 +736,13 @@
 
 
 void DofMap::distribute_local_dofs_node_major(unsigned int &next_free_dof,
-                                              MeshBase& mesh,
-                                              const bool build_send_list)
+                                              MeshBase& mesh)
 {
   const unsigned int sys_num = this->sys_number();
   const unsigned int n_vars  = this->n_variables();
 
-  // Number of elements to add to send_list
-  unsigned int send_list_size = 0;
+  // We now only add remote dofs to the _send_list
+  // unsigned int send_list_size = 0;
 
   // _var_first_local_df does not work with node_major dofs
   _var_first_local_df.resize(n_vars+1);
@@ -781,17 +782,6 @@
                                         0,
                                         next_free_dof);
                    next_free_dof += node->n_comp(sys_num,var);
-
-                   // If we've been requested to, add local dofs to the
-                   // _send_list
-                   if (build_send_list)
-                     for (unsigned int index=0; 
index<node->n_comp(sys_num,var);
-                          index++)
-                       _send_list.push_back(node->dof_number(sys_num,
-                                                             var,
-                                                             index));
-                   else
-                     send_list_size += node->n_comp(sys_num,var);
                  }
              }
         }
@@ -810,17 +800,6 @@
                                   next_free_dof);
 
              next_free_dof += elem->n_comp(sys_num,var);
-              
-             // If we've been requested to, add local dofs to the
-             // _send_list
-             if (build_send_list)
-               for (unsigned int index=0; index<elem->n_comp(sys_num,var);
-                    index++)
-                 _send_list.push_back(elem->dof_number(sys_num,
-                                                       var,
-                                                       index));
-             else
-               send_list_size += elem->n_comp(sys_num,var);
            }
     } // done looping over elements
 
@@ -845,25 +824,18 @@
         }
     }
 #endif // DEBUG
-
-  if (!build_send_list)
-    {
-      _send_list.clear();
-      _send_list.reserve(send_list_size);
-    }
 }
 
 
 
 void DofMap::distribute_local_dofs_var_major(unsigned int &next_free_dof,
-                                             MeshBase& mesh,
-                                             const bool build_send_list)
+                                             MeshBase& mesh)
 {
   const unsigned int sys_num = this->sys_number();
   const unsigned int n_vars  = this->n_variables();
 
-  // Number of elements to add to send_list
-  unsigned int send_list_size = 0;
+  // We now only add remote dofs to the _send_list
+  // unsigned int send_list_size = 0;
 
   // We will cache the first local index for each variable
   _var_first_local_df.clear();
@@ -909,17 +881,6 @@
                                        0,
                                        next_free_dof);
                   next_free_dof += node->n_comp(sys_num,var);
-
-                 // If we've been requested to, add local dofs to the
-                 // _send_list
-                  if (build_send_list)
-                    for (unsigned int index=0; index<node->n_comp(sys_num,var);
-                         index++)
-                      _send_list.push_back(node->dof_number(sys_num,
-                                                            var,
-                                                            index));
-                  else
-                    send_list_size += node->n_comp(sys_num,var);
                 }
             }
                   
@@ -935,17 +896,6 @@
                                    next_free_dof);
 
               next_free_dof += elem->n_comp(sys_num,var);
-              
-             // If we've been requested to, add local dofs to the
-             // _send_list
-              if (build_send_list)
-                for (unsigned int index=0; index<elem->n_comp(sys_num,var);
-                     index++)
-                  _send_list.push_back(elem->dof_number(sys_num,
-                                                      var,
-                                                      index));
-              else
-                send_list_size += elem->n_comp(sys_num,var);
             }
         } // end loop on elements
       _var_first_local_df.push_back(next_free_dof);
@@ -972,12 +922,6 @@
         }
     }
 #endif // DEBUG
-
-  if (!build_send_list)
-    {
-      _send_list.clear();
-      _send_list.reserve(send_list_size);
-    }
 }
 
 
@@ -987,7 +931,6 @@
   START_LOG("add_neighbors_to_send_list()", "DofMap");
   
   //-------------------------------------------------------------------------
-  // The _send_list now only contains entries from the local processor.
   // We need to add the DOFs from elements that live on neighboring processors
   // that are neighbors of the elements on the local processor
   //-------------------------------------------------------------------------
@@ -1032,10 +975,12 @@
                  // Get the DOF indices for this neighboring element
                  this->dof_indices (family[i], di);
 
-                 // Insert the DOF indices into the send list
-                 _send_list.insert (_send_list.end(),
-                                    di.begin(), di.end());
-               }
+                 // Insert the remote DOF indices into the send list
+                  for (unsigned int j=0; j != di.size(); ++j)
+                    if (di[j] < this->first_dof() ||
+                        di[j] >= this->end_dof())
+                     _send_list.push_back(di[j]);
+               }
          }
     }
 
@@ -1070,9 +1015,11 @@
          // Get the DOF indices for this neighboring element
          this->dof_indices (elem, di);
 
-         // Insert the DOF indices into the send list
-         _send_list.insert (_send_list.end(),
-                            di.begin(), di.end());
+         // Insert the remote DOF indices into the send list
+            for (unsigned int j=0; j != di.size(); ++j)
+              if (di[j] < this->first_dof() &&
+                  di[j] >= this->end_dof())
+               _send_list.push_back(di[j]);
        }
     }
   
@@ -1559,6 +1506,7 @@
 
 
 
+/*
 void DofMap::augment_send_list_for_projection(const MeshBase& mesh)
 {
   // Loop over the active local elements in the mesh.
@@ -1610,6 +1558,7 @@
   // The send-list might need to be sorted again.
   if (needs_sorting) this->sort_send_list ();
 }
+*/
 
 #endif // LIBMESH_ENABLE_AMR
 
Index: src/solvers/transient_system.C
===================================================================
--- src/solvers/transient_system.C      (Revision 3225)
+++ src/solvers/transient_system.C      (Arbeitskopie)
@@ -98,8 +98,10 @@
   Base::init_data();
 
   // Initialize the old & older solutions
-  old_local_solution->init   (this->n_dofs());
-  older_local_solution->init (this->n_dofs());
+  old_local_solution->init   (this->n_dofs(), this->n_local_dofs(),
+                              this->get_dof_map().get_send_list());
+  older_local_solution->init (this->n_dofs(), this->n_local_dofs(),
+                              this->get_dof_map().get_send_list());
 }
 
 
Index: src/solvers/system.C
===================================================================
--- src/solvers/system.C        (Revision 3225)
+++ src/solvers/system.C        (Arbeitskopie)
@@ -185,7 +185,8 @@
   solution->init (this->n_dofs(), this->n_local_dofs());
 
   // Resize the current_local_solution for the current mesh
-  current_local_solution->init (this->n_dofs());
+  current_local_solution->init (this->n_dofs(), this->n_local_dofs(),
+                                _dof_map->get_send_list());
 
   // from now on, no chance to add additional vectors
   _can_add_vectors = false;
@@ -211,19 +212,22 @@
         v->init (this->n_dofs(), this->n_local_dofs());
     }
 
+  const std::vector<unsigned int>& send_list = _dof_map->get_send_list ();
+
   // Restrict the solution on the coarsened cells
   if (_solution_projection)
     {
       this->project_vector (*solution);
       current_local_solution->clear();
-      current_local_solution->init(this->n_dofs());
-      const std::vector<unsigned int>& send_list = _dof_map->get_send_list ();
+      current_local_solution->init(this->n_dofs(),
+                                  this->n_local_dofs(), send_list);
       solution->localize (*current_local_solution, send_list); 
     }
   else
     {
       current_local_solution->clear();
-      current_local_solution->init(this->n_dofs());
+      current_local_solution->init(this->n_dofs(),
+                                   this->n_local_dofs(), send_list);
     }
 #endif
 }
@@ -257,7 +261,8 @@
   solution->init (this->n_dofs(), this->n_local_dofs());
        
   libmesh_assert (solution->size() == current_local_solution->size());
-  libmesh_assert (solution->size() == current_local_solution->local_size());
+  // Not true with ghosted vectors
+  // libmesh_assert (solution->size() == current_local_solution->local_size());
 
   const unsigned int first_local_dof = solution->first_local_index();
   const unsigned int local_size      = solution->local_size();
@@ -275,7 +280,7 @@
   const std::vector<unsigned int>& send_list = _dof_map->get_send_list ();
 
   // Check sizes
-  libmesh_assert (current_local_solution->local_size() == solution->size());
+  libmesh_assert (current_local_solution->size() == solution->size());
 // More processors than elements => empty send_list
 //  libmesh_assert (!send_list.empty());
   libmesh_assert (send_list.size() <= solution->size());
@@ -298,8 +303,9 @@
   Utility::iota (send_list.begin(), send_list.end(), 0);
   
   // Check sizes
-  libmesh_assert (current_local_solution->local_size() == solution->size());
   libmesh_assert (current_local_solution->size()       == solution->size());
+  // Not true with ghosted vectors
+  // libmesh_assert (current_local_solution->local_size() == solution->size());
   libmesh_assert (!send_list.empty());
   libmesh_assert (send_list.size() <= solution->size());
 
------------------------------------------------------------------------------
This SF.net email is sponsored by:
SourcForge Community
SourceForge wants to tell your story.
http://p.sf.net/sfu/sf-spreadtheword
_______________________________________________
Libmesh-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libmesh-devel

Reply via email to