Mercurial > fem-fenics-eugenio
view src/PETSc_factory.cc @ 268:61830a4f9ab9
Improve formatting
author | Eugenio Gianniti <eugenio.gianniti@mail.polimi.it> |
---|---|
date | Thu, 14 Aug 2014 12:26:55 +0200 |
parents | 8fe68d94ab76 |
children |
line wrap: on
line source
/* Copyright (C) 2014 Eugenio Gianniti <eugenio.gianniti@mail.polimi.it> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, see <http://www.gnu.org/licenses/>. */ #include "PETSc_factory.h" #ifdef LATEST_DOLFIN #include <boost/mpi.hpp> #include <boost/serialization/vector.hpp> #endif femfenics_base_factory const & PETSc_factory::instance (void) { static PETSc_factory const theinstance; return theinstance; } octave_value PETSc_factory::matrix (dolfin::Matrix const & A) const { octave_value retval; unsigned const size = #ifdef LATEST_DOLFIN dolfin::MPI::size (MPI_COMM_WORLD); #else dolfin::MPI::num_processes (); #endif if (size > 1) { retval = do_matrix_parallel (A); } else { retval = do_matrix_serial (A); } return retval; } octave_value PETSc_factory::vector (dolfin::Vector const & b) const { octave_value retval; unsigned const size = #ifdef LATEST_DOLFIN dolfin::MPI::size (MPI_COMM_WORLD); #else dolfin::MPI::num_processes (); #endif if (size > 1) { retval = do_vector_parallel (b); } else { retval = do_vector_serial (b); } return retval; } void PETSc_factory::add_to_arrays (Array <octave_idx_type> & ridx, Array <octave_idx_type> & cidx, Array <double> & values, std::vector <std::size_t> const & row, std::vector <std::size_t> const & col, std::vector <double> const & val) { octave_idx_type pos = cidx.numel (); dim_vector dims = cidx.dims (); if (dims(1) == 1) { dims(0) += col.size (); } else { dims(1) += col.size (); } ridx.resize (dims, 0); cidx.resize (dims, 0); values.resize (dims, 0); std::vector <std::size_t>::const_iterator rit = row.begin (), cit = col.begin (); std::vector <double>::const_iterator vit = val.begin (); while (cit != col.end ()) { ridx(pos) = *rit; cidx(pos) = *cit; values(pos) = *vit; ++rit; ++cit; ++vit; ++pos; } return; } octave_value PETSc_factory::do_matrix_serial (dolfin::Matrix const & A) const { octave_value retval; std::size_t nr = A.size (0), nc = A.size (1); dim_vector dims (0, 1); Array <octave_idx_type> ridx (dims, 0), cidx (dims, 0); Array<double> data (dims, 0); for (std::size_t i = 0; i < nr; ++i) { std::vector <double> data_tmp; std::vector <std::size_t> cidx_tmp; A.getrow (i, cidx_tmp, data_tmp); std::vector <std::size_t> ridx_tmp (cidx_tmp.size (), i); add_to_arrays (ridx, cidx, data, ridx_tmp, cidx_tmp, data_tmp); } SparseMatrix sm (data, ridx, cidx, nr, nc); retval = sm; return retval; } octave_value PETSc_factory::do_matrix_parallel (dolfin::Matrix const & A) const { octave_value retval; std::vector <std::size_t> rows, cols; std::vector <double> vals; std::size_t const nrows = A.size (0), ncols = A.size (1); std::pair <std::size_t, std::size_t> const range = A.local_range (0); for (std::size_t i = range.first; i < range.second; ++i) { std::vector <std::size_t> cols_tmp; std::vector <double> vals_tmp; A.getrow (i, cols_tmp, vals_tmp); cols.insert (cols.end (), cols_tmp.begin (), cols_tmp.end ()); vals.insert (vals.end (), vals_tmp.begin (), vals_tmp.end ()); for (std::size_t j = 0; j < cols_tmp.size (); ++j) { rows.push_back (i); } } boost::mpi::communicator world; unsigned const size = world.size (); unsigned const rank = world.rank (); for (unsigned p = 1; p < size; ++p) { if (rank == p) { unsigned const tag = 3 * (p - 1); world.send (0, tag, rows); world.send (0, tag + 1, cols); world.send (0, tag + 2, vals); } } if (rank == 0) { dim_vector dims (0, 1); Array <octave_idx_type> ridx (dims, 0), cidx (dims, 0); Array <double> data (dims, 0); add_to_arrays (ridx, cidx, data, rows, cols, vals); for (unsigned p = 1; p < size; ++p) { std::vector <double> new_vals; std::vector <std::size_t> new_rows, new_cols; unsigned const tag = 3 * (p - 1); world.recv (p, tag, new_rows); world.recv (p, tag + 1, new_cols); world.recv (p, tag + 2, new_vals); add_to_arrays (ridx, cidx, data, new_rows, new_cols, new_vals); } SparseMatrix sm (data, ridx, cidx, nrows, ncols); retval = sm; } else // Return an identity matrix just to avoid warnings or errors { dim_vector dims (nrows, 1); Array <octave_idx_type> ridx (dims), cidx (dims); Array <double> data (dims, 1); for (std::size_t i = 0; i < nrows; ++i) { ridx.xelem (i) = i; cidx.xelem (i) = i; } SparseMatrix sm (data, ridx, cidx, nrows, ncols); retval = sm; } return retval; } octave_value PETSc_factory::do_vector_serial (dolfin::Vector const & b) const { octave_value retval; dim_vector dims; dims.resize (2); dims(0) = b.size (); dims(1) = 1; Array <double> myb (dims); for (std::size_t i = 0; i < b.size (); ++i) { myb.xelem (i) = b[i]; } retval = myb; return retval; } octave_value PETSc_factory::do_vector_parallel (dolfin::Vector const & b) const { octave_value retval; std::size_t const length = b.size (); dim_vector dims (length, 1); Array <double> vec (dims, 0); std::vector <double> entries; b.gather_on_zero (entries); #ifdef LATEST_DOLFIN if (dolfin::MPI::rank (MPI_COMM_WORLD) == 0) #else if (dolfin::MPI::process_number () == 0) #endif for (std::size_t i = 0; i < length; ++i) { vec.xelem (i) = entries[i]; } // On nodes other than zero, return an all zero vector of the right length retval = vec; return retval; }