On Tue, 9 Sep 2008, John Peterson wrote:

Did you send a patch to the list? I'm going back through my email but
not seeing it...

No, just to Tim (and Ben, since he'd mentioned having some time to
benchmark a hopefully similar problem).  When the patch didn't show
any clear improvement, I didn't bother with sending it to the rest of
the list... but I might as well attach it now, for anyone who's
curious.  It was my attempt to cause the project_vector localize()
calls to only transfer necessary data, not fill a whole serial vector.

Depending on what the patch changes, the rest of this email might be
irrelevant ;-)

No, I think the set() calls are a separate issue.
---
Roy
Index: src/solvers/system_projection.C
===================================================================
--- src/solvers/system_projection.C     (revision 3010)
+++ src/solvers/system_projection.C     (working copy)
@@ -70,6 +70,8 @@
    */
   new_v.clear();
 
+#ifdef ENABLE_AMR 
+
   // Resize the new vector and get a serial version.
   NumericVector<Number> *new_vector_ptr;
   AutoPtr<NumericVector<Number> > new_vector_built;
@@ -91,6 +93,24 @@
   // we need to localize.
   else
     {
+      // Build a send list for efficient localization
+      std::vector<unsigned int> send_list;
+      Threads::parallel_for (
+        ConstElemRange (this->get_mesh().active_local_elements_begin(),
+                        this->get_mesh().active_local_elements_end()),
+                        BuildProjectionList(*this, send_list));
+      // Sort the send list.  After this duplicated
+      // elements will be adjacent in the vector
+      std::sort(send_list.begin(), send_list.end());
+
+      // Now use std::unique to remove duplicate entries
+      std::vector<unsigned int>::iterator new_end =
+        std::unique (send_list.begin(), send_list.end());
+
+      // Remove the end of the send_list.  Use the "swap trick"
+      // from Effective STL
+      std::vector<unsigned int> (send_list.begin(), new_end).swap (send_list);
+
       new_v.init (this->n_dofs(),
                  this->n_local_dofs());
       new_vector_built = NumericVector<Number>::build();
@@ -99,7 +119,7 @@
       local_old_vector = local_old_vector_built.get();
       new_vector_ptr->init(this->n_dofs(), this->n_dofs());
       local_old_vector->init(old_v.size(), old_v.size());
-      old_v.localize(*local_old_vector);
+      old_v.localize(*local_old_vector, send_list);
       local_old_vector->close();
       old_vector_ptr = local_old_vector;
     }
@@ -108,8 +128,6 @@
   NumericVector<Number> &new_vector = *new_vector_ptr;
   const NumericVector<Number> &old_vector = *old_vector_ptr;
     
-#ifdef ENABLE_AMR 
-
   Threads::parallel_for (ConstElemRange 
(this->get_mesh().active_local_elements_begin(),
                                         
this->get_mesh().active_local_elements_end(),
                                         1000),
@@ -122,6 +140,9 @@
 
   // If the old vector was serial, we probably need to send our values
   // to other processors
+  //
+  // FIXME: I'm not sure how to make a NumericVector do that without
+  // creating a temporary parallel vector to use localize! - RHS
   if (old_v.size() == old_v.local_size())
     {
       AutoPtr<NumericVector<Number> > dist_v = NumericVector<Number>::build();
@@ -134,7 +155,7 @@
 
       dist_v->close();
 
-      dist_v->localize (new_v);
+      dist_v->localize (new_v, this->get_dof_map().get_send_list());
       new_v.close();
     }
   // If the old vector was parallel, we need to update it
@@ -155,7 +176,7 @@
 #else
 
   // AMR is disabled: simply copy the vector
-  new_vector = old_vector;
+  new_v = old_v;
   
 #endif // #ifdef ENABLE_AMR
 
@@ -604,8 +625,65 @@
 }
 
 
+#ifndef ENABLE_AMR
+void System::BuildProjectionList::operator()(const ConstElemRange &) const
+{
+  libmesh_error();
+#else
+void System::BuildProjectionList::operator()(const ConstElemRange &range) const
+{
+  // The number of variables in this system
+  const unsigned int n_variables = system.n_vars();
 
+  // The DofMap for this system
+  const DofMap& dof_map = system.get_dof_map();
 
+  // Loop over all the variables in the system
+  for (unsigned int var=0; var<n_variables; var++)
+    {
+      // The old global DOF indices
+      std::vector<unsigned int> di;
+   
+      // Iterate over the elements in the range
+      for (ConstElemRange::const_iterator elem_it=range.begin(); elem_it != 
range.end(); ++elem_it)
+       {
+         const Elem* elem = *elem_it;
+         const Elem* parent = elem->parent();
+
+         if (elem->refinement_flag() == Elem::JUST_REFINED)
+           {
+             libmesh_assert (parent != NULL);
+              unsigned int old_parent_level = parent->p_level();
+
+              if (elem->p_refinement_flag() == Elem::JUST_REFINED)
+                {
+                  // We may have done p refinement or coarsening as well;
+                  // if so then we need to reset the parent's p level
+                  // so we can get the right DoFs from it
+                  libmesh_assert(elem->p_level() > 0);
+                  (const_cast<Elem *>(parent))->hack_p_level(elem->p_level() - 
1);
+                }
+              else if (elem->p_refinement_flag() == Elem::JUST_COARSENED)
+                {
+                  (const_cast<Elem *>(parent))->hack_p_level(elem->p_level() + 
1);
+                }
+
+             dof_map.old_dof_indices (parent, di, var);
+              send_list.insert(send_list.end(), di.begin(), di.end());
+
+              // Fix up the parent's p level in case we changed it
+              (const_cast<Elem *>(parent))->hack_p_level(old_parent_level);
+            }
+         else
+           dof_map.old_dof_indices (elem, di, var);
+        
+          send_list.insert(send_list.end(), di.begin(), di.end());
+        }  // end elem loop
+    } // end variables loop
+#endif // ENABLE_AMR
+}
+
+
 void System::ProjectSolution::operator()(const ConstElemRange &range) const
 {
   // We need data to project
Index: include/solvers/system.h
===================================================================
--- include/solvers/system.h    (revision 3010)
+++ include/solvers/system.h    (working copy)
@@ -737,7 +737,7 @@
   /**
    * This class implements projecting a vector from 
    * an old mesh to the newly refined mesh.  This
-   * may be exectued in parallel on multiple threads.
+   * may be executed in parallel on multiple threads.
    */
   class ProjectVector 
   {
@@ -760,6 +760,29 @@
 
 
   /**
+   * This class builds the send_list of old dof indices
+   * whose coefficients are needed to perform a projection.
+   * This may be executed in parallel on multiple threads.
+   */
+  class BuildProjectionList
+  {
+  private:
+    const System                &system;
+    std::vector<unsigned int>   &send_list;
+
+  public:
+    BuildProjectionList (const System              &system_in,
+                         std::vector<unsigned int> &send_list_in) :
+    system(system_in),
+    send_list(send_list_in)
+    {}
+    
+    void operator()(const ConstElemRange &range) const;
+  };
+
+
+
+  /**
    * This class implements projecting a vector from 
    * an old mesh to the newly refined mesh.  This
    * may be exectued in parallel on multiple threads.
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Libmesh-users mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/libmesh-users

Reply via email to