⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mesh_communication.c

📁 一个用来实现偏微分方程中网格的计算库
💻 C
📖 第 1 页 / 共 4 页
字号:
  {        std::vector<unsigned int>       el_id;    std::vector<unsigned short int> side_id;    std::vector<short int>          bc_id;        boundary_info.build_side_list (el_id, side_id, bc_id);    libmesh_assert (el_id.size() == side_id.size());    libmesh_assert (el_id.size() == bc_id.size());        const unsigned int n_bcs = el_id.size();    // reserve an upper bound for the number of BCs    xfer_elem_bcs.reserve(3*n_bcs);    // populate the xfer_elem_bcs list with *local* elements only.    for (unsigned int bc=0; bc<n_bcs; bc++)      {	const Elem* elem = mesh.elem(el_id[bc]);		// sanity: be sure that the element returned by mesh.elem() really has id()==el_id[e]	libmesh_assert(elem != NULL);	libmesh_assert(elem->id() == el_id[bc]);	libmesh_assert(elem->level() == 0);	libmesh_assert(side_id[bc] < elem->n_sides());	if (elem->processor_id() == libMesh::processor_id())	  {	    xfer_elem_bcs.push_back(el_id[bc]);	    xfer_elem_bcs.push_back(side_id[bc]);	    xfer_elem_bcs.push_back(bc_id[bc]);	  }      }    } // done with element boundary conditions  // Get the nodal boundary conditions  {    std::vector<unsigned int> node_id;    std::vector<short int>    bc_id;        boundary_info.build_node_list (node_id, bc_id);    libmesh_assert (node_id.size() == bc_id.size());    const unsigned int n_bcs = node_id.size();    // reserve an upper bound for the number of BCs    xfer_node_bcs.reserve(2*n_bcs);    // populate the xfer_node_bcs witl *local* nodes only    for (unsigned int bc=0; bc<n_bcs; bc++)      {	const Node* node = mesh.node_ptr(node_id[bc]);		libmesh_assert(node != NULL);	libmesh_assert(node->id() == node_id[bc]);	if (node->processor_id() == libMesh::processor_id())	  {	    xfer_node_bcs.push_back(node_id[bc]);	    xfer_node_bcs.push_back(bc_id[bc]);	  }      }  } // done with nodal boundary conditions  // The xfer arrays now contain all the information for our  // local bcs, and we are about to get all the information for  // remote bcs.  Go ahead and clear the current boundary_info  // information and rebuild it after we get the remote data.  boundary_info.clear();    // Get the boundary condition information from adacent processors  Parallel::allgather (xfer_elem_bcs);  Parallel::allgather (xfer_node_bcs);  // Insert the elements  {    const unsigned int n_bcs = xfer_elem_bcs.size()/3;    for (unsigned int bc=0, cnt=0; bc<n_bcs; bc++)      {	const Elem* elem = mesh.elem(xfer_elem_bcs[cnt++]);	const unsigned short int side_id = xfer_elem_bcs[cnt++];	const short int bc_id = xfer_elem_bcs[cnt++];	boundary_info.add_side (elem, side_id, bc_id);	      }    // no need for this any more    xfer_elem_bcs.resize(0);  }    // Insert the nodes  {    const unsigned int n_bcs = xfer_node_bcs.size()/2;    for (unsigned int bc=0, cnt=0; bc<n_bcs; bc++)      {	const Node* node = mesh.node_ptr (xfer_node_bcs[cnt++]);	const short int bc_id = xfer_node_bcs[cnt++];	boundary_info.add_node (node, bc_id);      }  } #ifndef NDEBUG    // Make sure all processors agree on the number of boundary ids.  const unsigned int n_bc_ids = boundary_info.n_boundary_ids();  unsigned int global_n_bc_ids = n_bc_ids;    Parallel::max (global_n_bc_ids);  libmesh_assert (n_bc_ids == global_n_bc_ids);  #endif    STOP_LOG  ("allgather_bcs()","MeshCommunication");}#endif // HAVE_MPI// Functor for make_elems_parallel_consistent and// make_node_ids_parallel_consistentnamespace {struct SyncIds{typedef unsigned int datum;typedef void (MeshBase::*renumber_obj)(unsigned int, unsigned int);SyncIds(MeshBase &_mesh, renumber_obj _renumberer) :  mesh(_mesh),  renumber(_renumberer) {}MeshBase &mesh;renumber_obj renumber;// renumber_obj &renumber;// Find the id of each requested DofObject -// sync_dofobject_data_by_xyz already did the work for usvoid gather_data (const std::vector<unsigned int>& ids,                  std::vector<datum>& ids_out){  ids_out = ids;}void act_on_data (const std::vector<unsigned int>& old_ids,                  std::vector<datum>& new_ids){  for (unsigned int i=0; i != old_ids.size(); ++i)    if (old_ids[i] != new_ids[i])      (mesh.*renumber)(old_ids[i], new_ids[i]);}};}void MeshCommunication::make_node_ids_parallel_consistent  (MeshBase &mesh,   LocationMap<Node> &loc_map){  // This function must be run on all processors at once  parallel_only();  START_LOG ("make_node_ids_parallel_consistent()", "MeshCommunication");  SyncIds syncids(mesh, &MeshBase::renumber_node);  Parallel::sync_dofobject_data_by_xyz    (mesh.nodes_begin(), mesh.nodes_end(),     loc_map, syncids);  STOP_LOG ("make_node_ids_parallel_consistent()", "MeshCommunication");}void MeshCommunication::make_elems_parallel_consistent(MeshBase &mesh){  // This function must be run on all processors at once  parallel_only();  START_LOG ("make_elems_parallel_consistent()", "MeshCommunication");  SyncIds syncids(mesh, &MeshBase::renumber_elem);  Parallel::sync_element_data_by_parent_id    (mesh, mesh.active_elements_begin(),     mesh.active_elements_end(), syncids);  STOP_LOG ("make_elems_parallel_consistent()", "MeshCommunication");}// Functors for make_node_proc_ids_parallel_consistentnamespace {struct SyncProcIds{typedef unsigned int datum;SyncProcIds(MeshBase &_mesh) : mesh(_mesh) {}MeshBase &mesh;void gather_data (const std::vector<unsigned int>& ids,                  std::vector<datum>& data){  // Find the processor id of each requested node  data.resize(ids.size());  for (unsigned int i=0; i != ids.size(); ++i)    {      // Look for this point in the mesh      Node *node = mesh.node_ptr(ids[i]);      // We'd better find every node we're asked for      libmesh_assert (node);      // Return the node's correct processor id,      data[i] = node->processor_id();    }}void act_on_data (const std::vector<unsigned int>& ids,                  std::vector<datum> proc_ids){  // Set the ghost node processor ids we've now been informed of  for (unsigned int i=0; i != ids.size(); ++i)    {      Node *node = mesh.node_ptr(ids[i]);      node->processor_id() = proc_ids[i];    }}};}void MeshCommunication::make_node_proc_ids_parallel_consistent  (MeshBase& mesh,   LocationMap<Node>& loc_map){  START_LOG ("make_node_proc_ids_parallel_consistent()", "MeshCommunication");  // This function must be run on all processors at once  parallel_only();  // When this function is called, each section of a parallelized mesh  // should be in the following state:  //  // All nodes should have the exact same physical location on every  // processor where they exist.  //  // Local nodes should have unique authoritative ids,  // and processor ids consistent with all processors which own  // an element touching them.  //  // Ghost nodes touching local elements should have processor ids  // consistent with all processors which own an element touching  // them.    SyncProcIds sync(mesh);  Parallel::sync_dofobject_data_by_xyz    (mesh.nodes_begin(), mesh.nodes_end(), loc_map, sync);  STOP_LOG ("make_node_proc_ids_parallel_consistent()", "MeshCommunication");}void MeshCommunication::make_nodes_parallel_consistent  (MeshBase &mesh,   LocationMap<Node> &loc_map){  // This function must be run on all processors at once  parallel_only();  // Create the loc_map if it hasn't been done already  bool need_map_update = (mesh.nodes_begin() != mesh.nodes_end() &&                           loc_map.empty());  Parallel::max(need_map_update);  if (need_map_update)    loc_map.init(mesh);  // When this function is called, each section of a parallelized mesh  // should be in the following state:  //  // All nodes should have the exact same physical location on every  // processor where they exist.  //  // Local nodes should have unique authoritative ids,  // and processor ids consistent with all processors which own  // an element touching them.  //  // Ghost nodes touching local elements should have processor ids  // consistent with all processors which own an element touching  // them.  //  // Ghost nodes should have ids which are either already correct  // or which are in the "unpartitioned" id space.  // First, let's sync up processor ids.  Some of these processor ids  // may be "wrong" from coarsening, but they're right in the sense  // that they'll tell us who has the authoritative dofobject ids for  // each node.  this->make_node_proc_ids_parallel_consistent(mesh, loc_map);  // Second, sync up dofobject ids.  this->make_node_ids_parallel_consistent(mesh, loc_map);  // Finally, correct the processor ids to make DofMap happy  MeshTools::correct_node_proc_ids(mesh, loc_map);}void MeshCommunication::delete_remote_elements(ParallelMesh& mesh) const{  // The mesh should know it's about to be parallelized  libmesh_assert (!mesh.is_serial());  START_LOG("delete_remote_elements()", "MeshCommunication");  // FIXME - should these be "unsorted_set"s?  O(N) is O(N)...  std::vector<bool> local_nodes(mesh.max_node_id(), false);  std::vector<bool> semilocal_elems(mesh.max_elem_id(), false);  // We don't want to delete any element that shares a node  // with or is an ancestor of a local element.  MeshBase::const_element_iterator l_elem_it = mesh.local_elements_begin(),                                   l_end     = mesh.local_elements_end();  for (; l_elem_it != l_end; ++l_elem_it)    {      const Elem *elem = *l_elem_it;      for (unsigned int n=0; n != elem->n_nodes(); ++n)        local_nodes[elem->node(n)] = true;      while (elem)        {          semilocal_elems[elem->id()] = true;          elem = elem->parent();        }    }  // We don't want to delete any element that shares a node  // with or is an ancestor of an unpartitioned element either.  MeshBase::const_element_iterator    u_elem_it = mesh.unpartitioned_elements_begin(),    u_end     = mesh.unpartitioned_elements_end();    for (; u_elem_it != u_end; ++u_elem_it)    {      const Elem *elem = *u_elem_it;      for (unsigned int n=0; n != elem->n_nodes(); ++n)        local_nodes[elem->node(n)] = true;      while (elem)        {          semilocal_elems[elem->id()] = true;          elem = elem->parent();        }    }  // Flag all the elements that share nodes with  // local and unpartitioned elements, along with their ancestors  MeshBase::element_iterator nl_elem_it = mesh.not_local_elements_begin(),                             nl_end     = mesh.not_local_elements_end();  for (; nl_elem_it != nl_end; ++nl_elem_it)    {      const Elem *elem = *nl_elem_it;      for (unsigned int n=0; n != elem->n_nodes(); ++n)        if (local_nodes[elem->node(n)])          {            while (elem)              {                semilocal_elems[elem->id()] = true;                elem = elem->parent();              }            break;          }    }  // Delete all the elements we have no reason to save,  // starting with the most refined so that the mesh  // is valid at all intermediate steps  unsigned int n_levels = MeshTools::n_levels(mesh);  for (int l = n_levels - 1; l >= 0; --l)    {      MeshBase::element_iterator lev_elem_it = mesh.level_elements_begin(l),                                 lev_end     = mesh.level_elements_end(l);      for (; lev_elem_it != lev_end; ++lev_elem_it)        {          Elem *elem = *lev_elem_it;          libmesh_assert (elem);          if (!semilocal_elems[elem->id()])            {              // Make sure we don't leave any invalid pointers              elem->make_links_to_me_remote();              // delete_elem doesn't currently invalidate element              // iterators... that had better not change              mesh.delete_elem(elem);            }        }    }  STOP_LOG("delete_remote_elements()", "MeshCommunication");  // Now make sure the containers actually shrink - strip  // any newly-created NULL voids out of the element array  mesh.renumber_nodes_and_elements();}// // Pack all this information into one communication to avoid two latency hits// // For each element it is of the form// // [ level p_level r_flag p_flag etype subdomain_id // //   self_ID parent_ID which_child node_0 node_1 ... node_n]// // We cannot use unsigned int because parent_ID can be negative// void MeshCommunication::pack_element (std::vector<int> &conn, const Elem* elem) const// {//   libmesh_assert (elem != NULL);// #ifdef ENABLE_AMR//   conn.push_back (static_cast<int>(elem->level()));//   conn.push_back (static_cast<int>(elem->p_level()));//   conn.push_back (static_cast<int>(elem->refinement_flag()));//   conn.push_back (static_cast<int>(elem->p_refinement_flag()));// #endif//   conn.push_back (static_cast<int>(elem->type()));//   conn.push_back (static_cast<int>(elem->processor_id()));//   conn.push_back (static_cast<int>(elem->subdomain_id()));//   conn.push_back (elem->id());		// #ifdef ENABLE_AMR//   // use parent_ID of -1 to indicate a level 0 element//   if (elem->level() == 0)//     {//       conn.push_back(-1);//       conn.push_back(-1);//     }//   else//     {//       conn.push_back(elem->parent()->id());//       conn.push_back(elem->parent()->which_child_am_i(elem));//     }// #endif  //   for (unsigned int n=0; n<elem->n_nodes(); n++)//     conn.push_back (elem->node(n));		// }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -