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

📄 partitioner.c

📁 一个用来实现偏微分方程中网格的计算库
💻 C
📖 第 1 页 / 共 2 页
字号:
// $Id: partitioner.C 2895 2008-06-26 13:41:06Z benkirk $// The libMesh Finite Element Library.// Copyright (C) 2002-2007  Benjamin S. Kirk, John W. Peterson  // 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   -----------------------------------// Local Includes -----------------------------------#include "elem.h"#include "mesh_base.h"#include "parallel.h"#include "partitioner.h"#include "mesh_tools.h"#include "mesh_communication.h"#include "libmesh_logging.h"// ------------------------------------------------------------// Partitioner static dataconst unsigned int Partitioner::communication_blocksize = 1000000;// ------------------------------------------------------------// Partitioner implementationvoid Partitioner::partition (MeshBase& mesh,			     const unsigned int n){  // BSK - temporary fix while redistribution is integrated 6/26/2008  // Uncomment this to not repartition in parallel   if (!mesh.is_serial())     return;  // we cannot partition into more pieces than we have  // active elements!  const unsigned int n_parts =    std::min(mesh.n_active_elem(), n);    // Set the number of partitions in the mesh  mesh.set_n_partitions()=n_parts;  if (n_parts == 1)    {      this->single_partition (mesh);      return;    }    // First assign a temporary partitioning to any unpartitioned elements  Partitioner::partition_unpartitioned_elements(mesh, n_parts);    // Call the partitioning function  this->_do_partition(mesh,n_parts);  // Set the parent's processor ids  Partitioner::set_parent_processor_ids(mesh);  // Set the node's processor ids  Partitioner::set_node_processor_ids(mesh);}void Partitioner::repartition (MeshBase& mesh,			       const unsigned int n){  // we cannot partition into more pieces than we have  // active elements!  const unsigned int n_parts =    std::min(mesh.n_active_elem(), n);    // Set the number of partitions in the mesh  mesh.set_n_partitions()=n_parts;  if (n_parts == 1)    {      this->single_partition (mesh);      return;    }    // First assign a temporary partitioning to any unpartitioned elements  Partitioner::partition_unpartitioned_elements(mesh, n_parts);    // Call the partitioning function  this->_do_repartition(mesh,n_parts);    // Set the parent's processor ids  Partitioner::set_parent_processor_ids(mesh);    // Set the node's processor ids  Partitioner::set_node_processor_ids(mesh);}void Partitioner::single_partition (MeshBase& mesh){  START_LOG("single_partition()","Partitioner");    // Loop over all the elements and assign them to processor 0.  MeshBase::element_iterator       elem_it  = mesh.elements_begin();  const MeshBase::element_iterator elem_end = mesh.elements_end();   for ( ; elem_it != elem_end; ++elem_it)    (*elem_it)->processor_id() = 0;  // For a single partition, all the nodes are on processor 0  MeshBase::node_iterator       node_it  = mesh.nodes_begin();  const MeshBase::node_iterator node_end = mesh.nodes_end();    for ( ; node_it != node_end; ++node_it)    (*node_it)->processor_id() = 0;  STOP_LOG("single_partition()","Partitioner");}void Partitioner::partition_unpartitioned_elements (MeshBase &mesh,						    const unsigned int n_subdomains){  MeshBase::const_element_iterator       it  = mesh.unpartitioned_elements_begin();  const MeshBase::const_element_iterator end = mesh.unpartitioned_elements_end();  const unsigned int n_unpartitioned_elements = MeshTools::n_elem (it, end);  // the unpartitioned elements must exist on all processors. If the range is empty on one  // it is empty on all, and we can quit right here.  if (!n_unpartitioned_elements) return;	   // find the target subdomain sizes  std::vector<unsigned int> subdomain_bounds(libMesh::n_processors());  for (unsigned int pid=0; pid<libMesh::n_processors(); pid++)    {      unsigned int tgt_subdomain_size = 0;      // watch out for the case that n_subdomains < n_processors      if (pid < n_subdomains)	{	  tgt_subdomain_size = n_unpartitioned_elements/n_subdomains;      	  if (pid < n_unpartitioned_elements%n_subdomains)	    tgt_subdomain_size++;	}            //std::cout << "pid, #= " << pid << ", " << tgt_subdomain_size << std::endl;      if (pid == 0)	subdomain_bounds[0] = tgt_subdomain_size;      else	subdomain_bounds[pid] = subdomain_bounds[pid-1] + tgt_subdomain_size;    }    libmesh_assert (subdomain_bounds.back() == n_unpartitioned_elements);      // create the unique mapping for all unpartitioned elements independent of partitioning  // determine the global indexing for all the unpartitoned elements  std::vector<unsigned int> global_indices;      // Calling this on all processors a unique range in [0,n_unpartitioned_elements) is constructed.    // Only the indices for the elements we pass in are returned in the array.  MeshCommunication().find_global_indices (MeshTools::bounding_box(mesh), it, end, 					   global_indices);    for (unsigned int cnt=0; it != end; ++it)    {      Elem *elem = *it;            libmesh_assert (cnt < global_indices.size());      const unsigned int global_index =	global_indices[cnt++];            libmesh_assert (global_index < subdomain_bounds.back());      libmesh_assert (global_index < n_unpartitioned_elements);      const unsigned int subdomain_id =	std::distance(subdomain_bounds.begin(),		      std::upper_bound(subdomain_bounds.begin(),				       subdomain_bounds.end(),				       global_index));      libmesh_assert (subdomain_id < n_subdomains);           elem->processor_id() = subdomain_id;		      //std::cout << "assigning " << global_index << " to " << subdomain_id << std::endl;	          }}void Partitioner::set_parent_processor_ids(MeshBase& mesh){  START_LOG("set_parent_processor_ids()","Partitioner");    // If the mesh is serial we have access to all the elements,  // in particular all the active ones.  We can therefore set  // the parent processor ids indirecly through their children.  // By convention a parent is assigned to the minimum processor  // of all its children.  if (mesh.is_serial())    {      // Loop over all the active elements in the mesh        MeshBase::element_iterator       it  = mesh.active_elements_begin();      const MeshBase::element_iterator end = mesh.active_elements_end();            for ( ; it!=end; ++it)	{#ifdef ENABLE_AMR	  Elem *child  = *it;	  Elem *parent = child->parent();	  while (parent)	    {	      // invalidate the parent id, otherwise the min below	      // will not work if the current parent id is less	      // than all the children!	      parent->invalidate_processor_id();	      	      for(unsigned int c=0; c<parent->n_children(); c++)		{		  child = parent->child(c);		  libmesh_assert(child);		  libmesh_assert(!child->is_remote());		  libmesh_assert(child->processor_id() != DofObject::invalid_processor_id);		  parent->processor_id() = std::min(parent->processor_id(),						    child->processor_id());		}	      	      parent = parent->parent();	    }#else	  libmesh_assert ((*it)->level() == 0);#endif	  	}    }  // When the mesh is parallel we cannot guarantee that parents have access to  // all their children.  else    {      // We will use a brute-force approach here.  Each processor finds its parent      // elements and sets the parent pid to the minimum of its local children.      // A global reduction is then performed to make sure the true minimum is found.      // As noted, this is required because we cannot guarantee that a parent has      // access to all its children on any single processor.      parallel_only();      libmesh_assert(MeshTools::n_elem(mesh.unpartitioned_elements_begin(),			       mesh.unpartitioned_elements_end()) == 0);      const unsigned int max_elem_id = mesh.max_elem_id();      std::vector<unsigned short int>	parent_processor_ids (std::min(communication_blocksize,				       max_elem_id));      

⌨️ 快捷键说明

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