<commit_before>// The libMesh Finite Element Library.
// Copyright (C) 2002-2014 <NAME>, <NAME>, <NAME>

// 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.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA



// C++ Includes   -----------------------------------
#include <numeric>

// Local Includes -----------------------------------
#include "libmesh/boundary_info.h"
#include "libmesh/elem.h"
#include "libmesh/libmesh_config.h"
#include "libmesh/libmesh_common.h"
#include "libmesh/libmesh_logging.h"
#include "libmesh/mesh_base.h"
#include "libmesh/mesh_communication.h"
#include "libmesh/mesh_inserter_iterator.h"
#include "libmesh/mesh_tools.h"
#include "libmesh/parallel.h"
#include "libmesh/parallel_elem.h"
#include "libmesh/parallel_mesh.h"
#include "libmesh/parallel_node.h"
#include "libmesh/parallel_ghost_sync.h"
#include "libmesh/utility.h"
#include "libmesh/remote_elem.h"



//-----------------------------------------------
// anonymous namespace for implementation details
namespace {

using namespace libMesh;

/**
 * Specific weak ordering for Elem*'s to be used in a set.
 * We use the id, but first sort by level.  This guarantees
 * when traversing the set from beginning to end the lower
 * level (parent) elements are encountered first.
 */
struct CompareElemIdsByLevel
{
  bool operator()(const Elem *a,
                  const Elem *b) const
  {
    libmesh_assert (a);
    libmesh_assert (b);
    const unsigned int
      al = a->level(), bl = b->level();
    const dof_id_type
      aid = a->id(),   bid = b->id();

    return (al == bl) ? aid < bid : al < bl;
  }
};
}


namespace libMesh
{


// ------------------------------------------------------------
// MeshCommunication class members
void MeshCommunication::clear ()
{
  //  _neighboring_processors.clear();
}



#ifndef LIBMESH_HAVE_MPI // avoid spurious gcc warnings
// ------------------------------------------------------------
void MeshCommunication::redistribute (ParallelMesh &) const
{
  // no MPI == one processor, no redistribution
  return;
}
#else
// ------------------------------------------------------------
void MeshCommunication::redistribute (ParallelMesh &mesh) const
{
  // This method will be called after a new partitioning has been
  // assigned to the elements.  This partitioning was defined in
  // terms of the active elements, and "trickled down" to the
  // parents and nodes as to be consistent.
  //
  // The point is that the entire concept of local elements is
  // kinda shaky in this method.  Elements which were previously
  // local may now be assigned to other processors, so we need to
  // send those off.  Similarly, we need to accept elements from
  // other processors.
  //
  // The approach is as follows:
  // (1) send all elements we have stored to their proper homes
  // (2) receive elements from all processors, watching for duplicates
  // (3) deleting all nonlocal elements elements
  // (4) obtaining required ghost elements from neighboring processors
  libmesh_parallel_only(mesh.comm());
  libmesh_assert (!mesh.is_serial());
  libmesh_assert (MeshTools::n_elem(mesh.unpartitioned_elements_begin(),
                                    mesh.unpartitioned_elements_end()) == 0);

  START_LOG("redistribute()","MeshCommunication");

  // Get a few unique message tags to use in communications; we'll
  // default to some numbers around pi*1000
  Parallel::MessageTag
    nodestag   = mesh.comm().get_unique_tag(3141),
    elemstag   = mesh.comm().get_unique_tag(3142);

  // Figure out how many nodes and elements we have which are assigned to each
  // processor.  send_n_nodes_and_elem_per_proc contains the number of nodes/elements
  // we will be sending to each processor, recv_n_nodes_and_elem_per_proc contains
  // the number of nodes/elements we will be receiving from each processor.
  // Format:
  //  send_n_nodes_and_elem_per_proc[2*pid+0] = number of nodes to send to pid
  //  send_n_nodes_and_elem_per_proc[2*pid+1] = number of elements to send to pid
  std::vector<dof_id_type> send_n_nodes_and_elem_per_proc(2*mesh.n_processors(), 0);

  std::vector<Parallel::Request>
    node_send_requests, element_send_requests;

  for (processor_id_type pid=0; pid<mesh.n_processors(); pid++)
    if (pid != mesh.processor_id()) // don't send to ourselves!!
      {
        // Build up a list of nodes and elements to send to processor pid.
        // We will certainly send all the elements assigned to this processor,
        // but we will also ship off any other elements which touch
        // their nodes.
        std::set<const Node*> connected_nodes;
        {
          MeshBase::const_element_iterator       elem_it  = mesh.pid_elements_begin(pid);
          const MeshBase::const_element_iterator elem_end = mesh.pid_elements_end(pid);

          for (; elem_it!=elem_end; ++elem_it)
            {
              const Elem* elem = *elem_it;

              for (unsigned int n=0; n<elem->n_nodes(); n++)
                connected_nodes.insert (elem->get_node(n));
            }
        }

        std::set<const Elem*, CompareElemIdsByLevel> elements_to_send;
        {
          MeshBase::const_element_iterator       elem_it  = mesh.elements_begin();
          const MeshBase::const_element_iterator elem_end = mesh.elements_end();

          for (; elem_it!=elem_end; ++elem_it)
            {
              const Elem* elem = *elem_it;

              for (unsigned int n=0; n<elem->n_nodes(); n++)
                if (connected_nodes.count(elem->get_node(n)))
                  elements_to_send.insert (elem);
            }
        }

        connected_nodes.clear();
        {
          std::set<const Elem*, CompareElemIdsByLevel>::iterator
            elem_it  = elements_to_send.begin(),
            elem_end = elements_to_send.end();

          for (; elem_it!=elem_end; ++elem_it)
            {
              const Elem* elem = *elem_it;

              for (unsigned int n=0; n<elem->n_nodes(); n++)
                connected_nodes.insert(elem->get_node(n));
            }
        }
<commit_msg>Don't miss redistributing any element ancestors<commit_after>// The libMesh Finite Element Library.
// Copyright (C) 2002-2014 <NAME>, <NAME>, <NAME>

// 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.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.

// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA



// C++ Includes   -----------------------------------
#include <numeric>

// Local Includes -----------------------------------
#include "libmesh/boundary_info.h"
#include "libmesh/elem.h"
#include "libmesh/libmesh_config.h"
#include "libmesh/libmesh_common.h"
#include "libmesh/libmesh_logging.h"
#include "libmesh/mesh_base.h"
#include "libmesh/mesh_communication.h"
#include "libmesh/mesh_inserter_iterator.h"
#include "libmesh/mesh_tools.h"
#include "libmesh/parallel.h"
#include "libmesh/parallel_elem.h"
#include "libmesh/parallel_mesh.h"
#include "libmesh/parallel_node.h"
#include "libmesh/parallel_ghost_sync.h"
#include "libmesh/utility.h"
#include "libmesh/remote_elem.h"



//-----------------------------------------------
// anonymous namespace for implementation details
namespace {

using namespace libMesh;

/**
 * Specific weak ordering for Elem*'s to be used in a set.
 * We use the id, but first sort by level.  This guarantees
 * when traversing the set from beginning to end the lower
 * level (parent) elements are encountered first.
 */
struct CompareElemIdsByLevel
{
  bool operator()(const Elem *a,
                  const Elem *b) const
  {
    libmesh_assert (a);
    libmesh_assert (b);
    const unsigned int
      al = a->level(), bl = b->level();
    const dof_id_type
      aid = a->id(),   bid = b->id();

    return (al == bl) ? aid < bid : al < bl;
  }
};
}


namespace libMesh
{


// ------------------------------------------------------------
// MeshCommunication class members
void MeshCommunication::clear ()
{
  //  _neighboring_processors.clear();
}



#ifndef LIBMESH_HAVE_MPI // avoid spurious gcc warnings
// ------------------------------------------------------------
void MeshCommunication::redistribute (ParallelMesh &) const
{
  // no MPI == one processor, no redistribution
  return;
}
#else
// ------------------------------------------------------------
void MeshCommunication::redistribute (ParallelMesh &mesh) const
{
  // This method will be called after a new partitioning has been
  // assigned to the elements.  This partitioning was defined in
  // terms of the active elements, and "trickled down" to the
  // parents and nodes as to be consistent.
  //
  // The point is that the entire concept of local elements is
  // kinda shaky in this method.  Elements which were previously
  // local may now be assigned to other processors, so we need to
  // send those off.  Similarly, we need to accept elements from
  // other processors.
  //
  // The approach is as follows:
  // (1) send all elements we have stored to their proper homes
  // (2) receive elements from all processors, watching for duplicates
  // (3) deleting all nonlocal elements elements
  // (4) obtaining required ghost elements from neighboring processors
  libmesh_parallel_only(mesh.comm());
  libmesh_assert (!mesh.is_serial());
  libmesh_assert (MeshTools::n_elem(mesh.unpartitioned_elements_begin(),
                                    mesh.unpartitioned_elements_end()) == 0);

  START_LOG("redistribute()","MeshCommunication");

  // Get a few unique message tags to use in communications; we'll
  // default to some numbers around pi*1000
  Parallel::MessageTag
    nodestag   = mesh.comm().get_unique_tag(3141),
    elemstag   = mesh.comm().get_unique_tag(3142);

  // Figure out how many nodes and elements we have which are assigned to each
  // processor.  send_n_nodes_and_elem_per_proc contains the number of nodes/elements
  // we will be sending to each processor, recv_n_nodes_and_elem_per_proc contains
  // the number of nodes/elements we will be receiving from each processor.
  // Format:
  //  send_n_nodes_and_elem_per_proc[2*pid+0] = number of nodes to send to pid
  //  send_n_nodes_and_elem_per_proc[2*pid+1] = number of elements to send to pid
  std::vector<dof_id_type> send_n_nodes_and_elem_per_proc(2*mesh.n_processors(), 0);

  std::vector<Parallel::Request>
    node_send_requests, element_send_requests;

  for (processor_id_type pid=0; pid<mesh.n_processors(); pid++)
    if (pid != mesh.processor_id()) // don't send to ourselves!!
      {
        // Build up a list of nodes and elements to send to processor pid.
        // We will certainly send all the elements assigned to this processor,
        // but we will also ship off any other elements which touch
        // their nodes.
        std::set<const Node*> connected_nodes;
        {
          MeshBase::const_element_iterator       elem_it  = mesh.pid_elements_begin(pid);
          const MeshBase::const_element_iterator elem_end = mesh.pid_elements_end(pid);

          for (; elem_it!=elem_end; ++elem_it)
            {
              const Elem* elem = *elem_it;

              for (unsigned int n=0; n<elem->n_nodes(); n++)
                connected_nodes.insert (elem->get_node(n));
            }
        }

        std::set<const Elem*, CompareElemIdsByLevel> elements_to_send;
        {
          MeshBase::const_element_iterator       elem_it  = mesh.elements_begin();
          const MeshBase::const_element_iterator elem_end = mesh.elements_end();

          for (; elem_it!=elem_end; ++elem_it)
            {
              const Elem* elem = *elem_it;

              for (unsigned int n=0; n<elem->n_nodes(); n++)
                if (connected_nodes.count(elem->get_node(n)))
                  {
                    elements_to_send.insert (elem);

                    // The remote processor needs all its semilocal
                    // elements' ancestors, and it's possible that
                    // they might not all be connected to the remote
                    // processor's nodes.
                    for (const Elem* parent = elem->parent(); parent;
                         parent = parent->parent())
                      elements_to_send.insert(parent);
                  }
            }
        }

        connected_nodes.clear();
        {
          std::set<const Elem*, CompareElemIdsByLevel>::iterator
            elem_it  = elements_to_send.begin(),
            elem_end = elements_to_send.end();

          for (; elem_it!=elem_end; ++elem_it)
            {
              const Elem* elem = *elem_it;

              for (unsigned int n=0; n<elem->n_nodes(); n++)
                connected_nodes.insert(elem->get_node(n));
            }
        }

{'fraction_non_alphanumeric': 0.13838514680483593, 'fraction_numerical': 0.007340241796200345, 'mean_word_length': 2.40529282038716, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 43, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6620233', 'n_tokens_mistral': 4015, 'n_tokens_neox': 3831, 'n_words': 1270}