ViennaCL - The Vienna Computing Library  1.5.1
viennacl/linalg/detail/ilu/common.hpp
Go to the documentation of this file.
00001 #ifndef VIENNACL_LINALG_DETAIL_ILU_COMMON_HPP_
00002 #define VIENNACL_LINALG_DETAIL_ILU_COMMON_HPP_
00003 
00004 /* =========================================================================
00005    Copyright (c) 2010-2014, Institute for Microelectronics,
00006                             Institute for Analysis and Scientific Computing,
00007                             TU Wien.
00008    Portions of this software are copyright by UChicago Argonne, LLC.
00009 
00010                             -----------------
00011                   ViennaCL - The Vienna Computing Library
00012                             -----------------
00013 
00014    Project Head:    Karl Rupp                   rupp@iue.tuwien.ac.at
00015 
00016    (A list of authors and contributors can be found in the PDF manual)
00017 
00018    License:         MIT (X11), see file LICENSE in the base directory
00019 ============================================================================= */
00020 
00025 #include <vector>
00026 #include <cmath>
00027 #include <iostream>
00028 #include <map>
00029 #include <list>
00030 
00031 #include "viennacl/forwards.h"
00032 #include "viennacl/tools/tools.hpp"
00033 #include "viennacl/backend/memory.hpp"
00034 
00035 #include "viennacl/linalg/host_based/common.hpp"
00036 #include "viennacl/linalg/misc_operations.hpp"
00037 
00038 namespace viennacl
00039 {
00040   namespace linalg
00041   {
00042     namespace detail
00043     {
00044 
00045 
00046       //
00047       // Level Scheduling Setup for ILU:
00048       //
00049 
00050       template <typename ScalarType, unsigned int ALIGNMENT>
00051       void level_scheduling_setup_impl(viennacl::compressed_matrix<ScalarType, ALIGNMENT> const & LU,
00052                                        vector<ScalarType> const & diagonal_LU,
00053                                        std::list< viennacl::backend::mem_handle > & row_index_arrays,
00054                                        std::list< viennacl::backend::mem_handle > & row_buffers,
00055                                        std::list< viennacl::backend::mem_handle > & col_buffers,
00056                                        std::list< viennacl::backend::mem_handle > & element_buffers,
00057                                        std::list< vcl_size_t > & row_elimination_num_list,
00058                                        bool setup_U)
00059       {
00060         ScalarType   const * diagonal_buf = viennacl::linalg::host_based::detail::extract_raw_pointer<ScalarType>(diagonal_LU.handle());
00061         ScalarType   const * elements   = viennacl::linalg::host_based::detail::extract_raw_pointer<ScalarType>(LU.handle());
00062         unsigned int const * row_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(LU.handle1());
00063         unsigned int const * col_buffer = viennacl::linalg::host_based::detail::extract_raw_pointer<unsigned int>(LU.handle2());
00064 
00065         //
00066         // Step 1: Determine row elimination order for each row and build up meta information about the number of entries taking part in each elimination step:
00067         //
00068         std::vector<vcl_size_t> row_elimination(LU.size1());
00069         std::map<vcl_size_t, std::map<vcl_size_t, vcl_size_t> > row_entries_per_elimination_step;
00070 
00071         vcl_size_t max_elimination_runs = 0;
00072         for (vcl_size_t row2 = 0; row2 < LU.size1(); ++row2)
00073         {
00074           vcl_size_t row = setup_U ? (LU.size1() - row2) - 1 : row2;
00075 
00076           vcl_size_t row_begin = row_buffer[row];
00077           vcl_size_t row_end   = row_buffer[row+1];
00078           vcl_size_t elimination_index = 0;  //Note: first run corresponds to elimination_index = 1 (otherwise, type issues with int <-> unsigned int would arise
00079           for (vcl_size_t i = row_begin; i < row_end; ++i)
00080           {
00081             unsigned int col = col_buffer[i];
00082             if ( (!setup_U && col < row) || (setup_U && col > row) )
00083             {
00084               elimination_index = std::max<vcl_size_t>(elimination_index, row_elimination[col]);
00085               row_entries_per_elimination_step[row_elimination[col]][row] += 1;
00086             }
00087           }
00088           row_elimination[row] = elimination_index + 1;
00089           max_elimination_runs = std::max<vcl_size_t>(max_elimination_runs, elimination_index + 1);
00090         }
00091 
00092         //std::cout << "Number of elimination runs: " << max_elimination_runs << std::endl;
00093 
00094         //
00095         // Step 2: Build row-major elimination matrix for each elimination step
00096         //
00097 
00098         //std::cout << "Elimination order: " << std::endl;
00099         //for (vcl_size_t i=0; i<row_elimination.size(); ++i)
00100         //  std::cout << row_elimination[i] << ", ";
00101         //std::cout << std::endl;
00102 
00103         //vcl_size_t summed_rows = 0;
00104         for (vcl_size_t elimination_run = 1; elimination_run <= max_elimination_runs; ++elimination_run)
00105         {
00106           std::map<vcl_size_t, vcl_size_t> const & current_elimination_info = row_entries_per_elimination_step[elimination_run];
00107 
00108           // count cols and entries handled in this elimination step
00109           vcl_size_t num_tainted_cols = current_elimination_info.size();
00110           vcl_size_t num_entries = 0;
00111 
00112           for (std::map<vcl_size_t, vcl_size_t>::const_iterator it  = current_elimination_info.begin();
00113                                                                   it != current_elimination_info.end();
00114                                                                 ++it)
00115             num_entries += it->second;
00116 
00117           //std::cout << "num_entries: " << num_entries << std::endl;
00118           //std::cout << "num_tainted_cols: " << num_tainted_cols << std::endl;
00119 
00120           if (num_tainted_cols > 0)
00121           {
00122             row_index_arrays.push_back(viennacl::backend::mem_handle());
00123             viennacl::backend::switch_memory_context<unsigned int>(row_index_arrays.back(), viennacl::traits::context(LU));
00124             viennacl::backend::typesafe_host_array<unsigned int> elim_row_index_array(row_index_arrays.back(), num_tainted_cols);
00125 
00126             row_buffers.push_back(viennacl::backend::mem_handle());
00127             viennacl::backend::switch_memory_context<unsigned int>(row_buffers.back(), viennacl::traits::context(LU));
00128             viennacl::backend::typesafe_host_array<unsigned int> elim_row_buffer(row_buffers.back(), num_tainted_cols + 1);
00129 
00130             col_buffers.push_back(viennacl::backend::mem_handle());
00131             viennacl::backend::switch_memory_context<unsigned int>(col_buffers.back(), viennacl::traits::context(LU));
00132             viennacl::backend::typesafe_host_array<unsigned int> elim_col_buffer(col_buffers.back(), num_entries);
00133 
00134             element_buffers.push_back(viennacl::backend::mem_handle());
00135             viennacl::backend::switch_memory_context<ScalarType>(element_buffers.back(), viennacl::traits::context(LU));
00136             std::vector<ScalarType> elim_elements_buffer(num_entries);
00137 
00138             row_elimination_num_list.push_back(num_tainted_cols);
00139 
00140             vcl_size_t k=0;
00141             vcl_size_t nnz_index = 0;
00142             elim_row_buffer.set(0, 0);
00143 
00144             for (std::map<vcl_size_t, vcl_size_t>::const_iterator it  = current_elimination_info.begin();
00145                                                                     it != current_elimination_info.end();
00146                                                                   ++it)
00147             {
00148               //vcl_size_t col = setup_U ? (elimination_matrix.size() - it->first) - 1 : col2;
00149               vcl_size_t row = it->first;
00150               elim_row_index_array.set(k, row);
00151 
00152               vcl_size_t row_begin = row_buffer[row];
00153               vcl_size_t row_end   = row_buffer[row+1];
00154               for (vcl_size_t i = row_begin; i < row_end; ++i)
00155               {
00156                 unsigned int col = col_buffer[i];
00157                 if ( (!setup_U && col < row) || (setup_U && col > row) ) //entry of L/U
00158                 {
00159                   if (row_elimination[col] == elimination_run) // this entry is substituted in this run
00160                   {
00161                     elim_col_buffer.set(nnz_index, col);
00162                     elim_elements_buffer[nnz_index] = setup_U ? elements[i] / diagonal_buf[it->first] : elements[i];
00163                     ++nnz_index;
00164                   }
00165                 }
00166               }
00167 
00168               elim_row_buffer.set(++k, nnz_index);
00169             }
00170 
00171             //
00172             // Wrap in memory_handles:
00173             //
00174             viennacl::backend::memory_create(row_index_arrays.back(), elim_row_index_array.raw_size(),                  viennacl::traits::context(row_index_arrays.back()), elim_row_index_array.get());
00175             viennacl::backend::memory_create(row_buffers.back(),      elim_row_buffer.raw_size(),                       viennacl::traits::context(row_buffers.back()),      elim_row_buffer.get());
00176             viennacl::backend::memory_create(col_buffers.back(),      elim_col_buffer.raw_size(),                       viennacl::traits::context(col_buffers.back()),      elim_col_buffer.get());
00177             viennacl::backend::memory_create(element_buffers.back(),  sizeof(ScalarType) * elim_elements_buffer.size(), viennacl::traits::context(element_buffers.back()),  &(elim_elements_buffer[0]));
00178           }
00179 
00180           // Print some info:
00181           //std::cout << "Eliminated columns in run " << elimination_run << ": " << num_tainted_cols << " (tainted columns: " << num_tainted_cols << ")" << std::endl;
00182           //summed_rows += eliminated_rows_in_run;
00183           //if (eliminated_rows_in_run == 0)
00184           //  break;
00185         }
00186         //std::cout << "Eliminated rows: " << summed_rows << " out of " << row_elimination.size() << std::endl;
00187       }
00188 
00189 
00190       template <typename ScalarType, unsigned int ALIGNMENT>
00191       void level_scheduling_setup_L(viennacl::compressed_matrix<ScalarType, ALIGNMENT> const & LU,
00192                                 vector<ScalarType> const & diagonal_LU,
00193                                 std::list< viennacl::backend::mem_handle > & row_index_arrays,
00194                                 std::list< viennacl::backend::mem_handle > & row_buffers,
00195                                 std::list< viennacl::backend::mem_handle > & col_buffers,
00196                                 std::list< viennacl::backend::mem_handle > & element_buffers,
00197                                 std::list< vcl_size_t > & row_elimination_num_list)
00198       {
00199         level_scheduling_setup_impl(LU, diagonal_LU, row_index_arrays, row_buffers, col_buffers, element_buffers, row_elimination_num_list, false);
00200       }
00201 
00202 
00203       //
00204       // Multifrontal setup of U:
00205       //
00206 
00207       template <typename ScalarType, unsigned int ALIGNMENT>
00208       void level_scheduling_setup_U(viennacl::compressed_matrix<ScalarType, ALIGNMENT> const & LU,
00209                                 vector<ScalarType> const & diagonal_LU,
00210                                 std::list< viennacl::backend::mem_handle > & row_index_arrays,
00211                                 std::list< viennacl::backend::mem_handle > & row_buffers,
00212                                 std::list< viennacl::backend::mem_handle > & col_buffers,
00213                                 std::list< viennacl::backend::mem_handle > & element_buffers,
00214                                 std::list< vcl_size_t > & row_elimination_num_list)
00215       {
00216         level_scheduling_setup_impl(LU, diagonal_LU, row_index_arrays, row_buffers, col_buffers, element_buffers, row_elimination_num_list, true);
00217       }
00218 
00219 
00220       //
00221       // Multifrontal substitution (both L and U). Will partly be moved to single_threaded/opencl/cuda implementations
00222       //
00223       template <typename ScalarType>
00224       void level_scheduling_substitute(vector<ScalarType> & vec,
00225                                        std::list< viennacl::backend::mem_handle > const & row_index_arrays,
00226                                        std::list< viennacl::backend::mem_handle > const & row_buffers,
00227                                        std::list< viennacl::backend::mem_handle > const & col_buffers,
00228                                        std::list< viennacl::backend::mem_handle > const & element_buffers,
00229                                        std::list< vcl_size_t > const & row_elimination_num_list)
00230       {
00231         typedef typename std::list< viennacl::backend::mem_handle >::const_iterator  ListIterator;
00232         ListIterator row_index_array_it = row_index_arrays.begin();
00233         ListIterator row_buffers_it = row_buffers.begin();
00234         ListIterator col_buffers_it = col_buffers.begin();
00235         ListIterator element_buffers_it = element_buffers.begin();
00236         typename std::list< vcl_size_t>::const_iterator row_elimination_num_it = row_elimination_num_list.begin();
00237         for (vcl_size_t i=0; i<row_index_arrays.size(); ++i)
00238         {
00239           viennacl::linalg::detail::level_scheduling_substitute(vec, *row_index_array_it, *row_buffers_it, *col_buffers_it, *element_buffers_it, *row_elimination_num_it);
00240 
00241           ++row_index_array_it;
00242           ++row_buffers_it;
00243           ++col_buffers_it;
00244           ++element_buffers_it;
00245           ++row_elimination_num_it;
00246         }
00247       }
00248 
00249 
00250 
00251 
00252 
00253     } // namespace detail
00254   } // namespace linalg
00255 } // namespace viennacl
00256 
00257 
00258 
00259 
00260 #endif
00261 
00262 
00263