$extrastylesheet
sfc_partitioner.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
00003 
00004 // This library is free software; you can redistribute it and/or
00005 // modify it under the terms of the GNU Lesser General Public
00006 // License as published by the Free Software Foundation; either
00007 // version 2.1 of the License, or (at your option) any later version.
00008 
00009 // This library is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // Lesser General Public License for more details.
00013 
00014 // You should have received a copy of the GNU Lesser General Public
00015 // License along with this library; if not, write to the Free Software
00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018 
00019 
00020 // C++ Includes   -----------------------------------
00021 
00022 // Local Includes -----------------------------------
00023 #include "libmesh/libmesh_config.h"
00024 #include "libmesh/mesh_base.h"
00025 #include "libmesh/sfc_partitioner.h"
00026 #include "libmesh/libmesh_logging.h"
00027 #include "libmesh/elem.h"
00028 
00029 #ifdef LIBMESH_HAVE_SFCURVES
00030 namespace Sfc {
00031 extern "C" {
00032 #     include "sfcurves.h"
00033 }
00034 }
00035 #else
00036 #  include "libmesh/linear_partitioner.h"
00037 #endif
00038 
00039 namespace libMesh
00040 {
00041 
00042 
00043 // ------------------------------------------------------------
00044 // SFCPartitioner implementation
00045 void SFCPartitioner::_do_partition (MeshBase& mesh,
00046                                     const unsigned int n)
00047 {
00048 
00049   libmesh_assert_greater (n, 0);
00050 
00051   // Check for an easy return
00052   if (n == 1)
00053     {
00054       this->single_partition (mesh);
00055       return;
00056     }
00057 
00058   // What to do if the sfcurves library IS NOT present
00059 #ifndef LIBMESH_HAVE_SFCURVES
00060 
00061   libmesh_here();
00062   libMesh::err << "ERROR: The library has been built without"    << std::endl
00063                << "Space Filling Curve support.  Using a linear" << std::endl
00064                << "partitioner instead!" << std::endl;
00065 
00066   LinearPartitioner lp;
00067 
00068   lp.partition (mesh, n);
00069 
00070   // What to do if the sfcurves library IS present
00071 #else
00072 
00073   START_LOG("sfc_partition()", "SFCPartitioner");
00074 
00075   const dof_id_type n_active_elem = mesh.n_active_elem();
00076   const dof_id_type n_elem        = mesh.n_elem();
00077 
00078   // the forward_map maps the active element id
00079   // into a contiguous block of indices
00080   std::vector<dof_id_type>
00081     forward_map (n_elem, DofObject::invalid_id);
00082 
00083   // the reverse_map maps the contiguous ids back
00084   // to active elements
00085   std::vector<Elem*> reverse_map (n_active_elem, NULL);
00086 
00087   int size = static_cast<int>(n_active_elem);
00088   std::vector<double> x      (size);
00089   std::vector<double> y      (size);
00090   std::vector<double> z      (size);
00091   std::vector<int>    table  (size);
00092 
00093 
00094   // We need to map the active element ids into a
00095   // contiguous range.
00096   {
00097     //     active_elem_iterator       elem_it (mesh.elements_begin());
00098     //     const active_elem_iterator elem_end(mesh.elements_end());
00099 
00100     MeshBase::element_iterator       elem_it  = mesh.active_elements_begin();
00101     const MeshBase::element_iterator elem_end = mesh.active_elements_end();
00102 
00103     dof_id_type el_num = 0;
00104 
00105     for (; elem_it != elem_end; ++elem_it)
00106       {
00107         libmesh_assert_less ((*elem_it)->id(), forward_map.size());
00108         libmesh_assert_less (el_num, reverse_map.size());
00109 
00110         forward_map[(*elem_it)->id()] = el_num;
00111         reverse_map[el_num]           = *elem_it;
00112         el_num++;
00113       }
00114     libmesh_assert_equal_to (el_num, n_active_elem);
00115   }
00116 
00117 
00118   // Get the centroid for each active element
00119   {
00120     //     const_active_elem_iterator       elem_it (mesh.const_elements_begin());
00121     //     const const_active_elem_iterator elem_end(mesh.const_elements_end());
00122 
00123     MeshBase::element_iterator       elem_it  = mesh.active_elements_begin();
00124     const MeshBase::element_iterator elem_end = mesh.active_elements_end();
00125 
00126     for (; elem_it != elem_end; ++elem_it)
00127       {
00128         const Elem* elem = *elem_it;
00129 
00130         libmesh_assert_less (elem->id(), forward_map.size());
00131 
00132         const Point p = elem->centroid();
00133 
00134         x[forward_map[elem->id()]] = p(0);
00135         y[forward_map[elem->id()]] = p(1);
00136         z[forward_map[elem->id()]] = p(2);
00137       }
00138   }
00139 
00140   // build the space-filling curve
00141   if (_sfc_type == "Hilbert")
00142     Sfc::hilbert (&x[0], &y[0], &z[0], &size, &table[0]);
00143 
00144   else if (_sfc_type == "Morton")
00145     Sfc::morton  (&x[0], &y[0], &z[0], &size, &table[0]);
00146 
00147   else
00148     {
00149       libmesh_here();
00150       libMesh::err << "ERROR: Unknown type: " << _sfc_type << std::endl
00151                    << " Valid types are"                   << std::endl
00152                    << "  \"Hilbert\""                      << std::endl
00153                    << "  \"Morton\""                       << std::endl
00154                    << " "                                  << std::endl
00155                    << "Proceeding with a Hilbert curve."   << std::endl;
00156 
00157       Sfc::hilbert (&x[0], &y[0], &z[0], &size, &table[0]);
00158     }
00159 
00160 
00161   // Assign the partitioning to the active elements
00162   {
00163     //      {
00164     //        std::ofstream out ("sfc.dat");
00165     //        out << "variables=x,y,z" << std::endl;
00166     //        out << "zone f=point" << std::endl;
00167 
00168     //        for (unsigned int i=0; i<n_active_elem; i++)
00169     //  out << x[i] << " "
00170     //      << y[i] << " "
00171     //      << z[i] << std::endl;
00172     //      }
00173 
00174     const dof_id_type blksize = (n_active_elem+n-1)/n;
00175 
00176     for (dof_id_type i=0; i<n_active_elem; i++)
00177       {
00178         libmesh_assert_less (static_cast<unsigned int>(table[i]-1), reverse_map.size());
00179 
00180         Elem* elem = reverse_map[table[i]-1];
00181 
00182         elem->processor_id() = cast_int<processor_id_type>
00183           (i/blksize);
00184       }
00185   }
00186 
00187   STOP_LOG("sfc_partition()", "SFCPartitioner");
00188 
00189 #endif
00190 
00191 }
00192 
00193 } // namespace libMesh