MOOCHO (Single Doxygen Collection)  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
AbstractLinAlgPack_DirectSparseSolverSuperLU.cpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Moocho: Multi-functional Object-Oriented arCHitecture for Optimization
5 // Copyright (2003) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Roscoe A. Bartlett (rabartl@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #ifdef SPARSE_SOLVER_PACK_USE_SUPERLU
43 
44 #include <assert.h>
45 
46 #include <fstream>
47 #include <algorithm>
48 
53 #include "Teuchos_Assert.hpp"
54 #include "Teuchos_Workspace.hpp"
55 #include "Teuchos_dyn_cast.hpp"
56 
57 namespace {
58 
59 // Convert to compressed sparse row
60 void convet_to_csr(
61  int n
62  ,int m
63  ,int nz
64  ,const DenseLinAlgPack::value_type a_val[]
65  ,const DenseLinAlgPack::index_type a_row_i[]
66  ,const DenseLinAlgPack::index_type a_col_j[]
67  ,double acsr_val[]
68  ,int acsr_col_j[]
69  ,int acsr_row_ptr[]
70  )
71 {
72  // Count the number of entries per row and put in acsr_row_ptr[1...m+1]
73  std::fill_n( &acsr_row_ptr[0], m+1, 0 );
74  {for( int k = 0; k < nz; ++k ) {
75  ++acsr_row_ptr[a_row_i[k]]; // a_row_i[] is 1-based so this works out.
76  }}
77 
78  // Transform the counts of entries per row into the start pointers for the rows.
79  // We will make acsr_row_ptr[0] = 0 and then add form there. We will then
80  // shift this data so that acsr_row_ptr[1] = 0. This data
81  // structure will be used to fill the entries per row.
82  acsr_row_ptr[0] = 0;
83  {for( int i = 2; i < m + 1; ++i ) {
84  acsr_row_ptr[i] += acsr_row_ptr[i-1];
85  }}
86  {for( int i = m; i > 0; --i ) {
87  acsr_row_ptr[i] = acsr_row_ptr[i-1];
88  }}
89 
90  // Now copy into the compressed sparse row data structure
91  {for( int k = 0; k < nz; ++k ) {
92  const int row_i = a_row_i[k]; // one-based
93  const int row_ptr = acsr_row_ptr[row_i]; // returned value is zero-based
94  acsr_val[row_ptr] = a_val[k];
95  acsr_col_j[row_ptr] = a_col_j[row_ptr] - 1; // from one-based to zero-based
96  ++acsr_row_ptr[row_i];
97  }}
98  TEUCHOS_TEST_FOR_EXCEPT( !( acsr_row_ptr[m] == nz ) );
99 
100 }
101 
102 } // end namespace
103 
104 namespace AbstractLinAlgPack {
105 
106 //
107 // Implementation of DirectSparseSolver(Imp) interface using SuperLU.
108 //
109 // Here are some little bits of knowledge about SuperLU that I need
110 // to record after many hours of hard work.
111 //
112 // ToDo: Finish this!
113 //
114 
115 // ToDo:
116 // a) Add an option for printing the values of the common
117 // block parameters to out or to a file. This can
118 // be used to get a feel for the performance of
119 // ma28
120 // b) Add provisions for an external client to change
121 // the control options of SuperLU. Most of these are
122 // stored as common block variables.
123 
124 // //////////////////////////////////////////////////
125 // DirectSparseSolverSuperLU::BasisMatrixSuperLU
126 
127 // Overridden from BasisMatrixImp
128 
130 DirectSparseSolverSuperLU::BasisMatrixSuperLU::create_matrix() const
131 {
132  return Teuchos::rcp(new BasisMatrixSuperLU);
133 }
134 
136  VectorMutable* y, BLAS_Cpp::Transp M_trans, const Vector& x
137  ) const
138 {
139  using Teuchos::dyn_cast;
140  using Teuchos::Workspace;
142  size_type k;
143 
144  // Get concrete objects
145  const FactorizationStructureSuperLU
146  &fs = dyn_cast<const FactorizationStructureSuperLU>(*this->get_fact_struc());
147  const FactorizationNonzerosSuperLU
148  &fn = dyn_cast<const FactorizationNonzerosSuperLU>(*this->get_fact_nonzeros());
149 
150  VectorDenseMutableEncap yd(*y);
151  VectorDenseEncap xd(x);
152 
153  yd() = xd(); // Copy rhs into lhs for SuperLU
154 
155  fs.superlu_solver_->solve(
156  *fs.fact_struct_
157  ,*fn.fact_nonzeros_
158  ,M_trans == BLAS_Cpp::no_trans
159  ,yd().dim()
160  ,1
161  ,&yd()[0]
162  ,yd().dim()
163  );
164 
165 }
166 
167 // //////////////////////////////////////////////////
168 // DirectSparseSolverSuperLU::FactorizationStructureSuperLU
169 
170 DirectSparseSolverSuperLU::FactorizationStructureSuperLU::FactorizationStructureSuperLU()
171  :superlu_solver_(SuperLUPack::SuperLUSolver::create_solver())
172 {}
173 
174 // //////////////////////////////////////////////////
175 // DirectSparseSolverSuperLU
176 
177 // Constructors/initializers
178 
179 DirectSparseSolverSuperLU::DirectSparseSolverSuperLU()
180 {}
181 
182 // Overridden from DirectSparseSolver
183 
185 DirectSparseSolverSuperLU::basis_matrix_factory() const
186 {
187  namespace mmp = MemMngPack;
189 }
190 
191 void DirectSparseSolverSuperLU::estimated_fillin_ratio(
192  value_type estimated_fillin_ratio
193  )
194 {
196 }
197 
198 // Overridden from DirectSparseSolverImp
199 
201 DirectSparseSolverSuperLU::create_fact_struc() const
202 {
203  return Teuchos::rcp(new FactorizationStructureSuperLU);
204 }
205 
207 DirectSparseSolverSuperLU::create_fact_nonzeros() const
208 {
209  return Teuchos::rcp(new FactorizationNonzerosSuperLU);
210 }
211 
212 void DirectSparseSolverSuperLU::imp_analyze_and_factor(
214  ,FactorizationStructure *fact_struc
215  ,FactorizationNonzeros *fact_nonzeros
216  ,DenseLinAlgPack::IVector *row_perm
217  ,DenseLinAlgPack::IVector *col_perm
218  ,size_type *rank
219  ,std::ostream *out
220  )
221 {
222  namespace mmp = MemMngPack;
223  using Teuchos::dyn_cast;
224  typedef MatrixConvertToSparse MCTS;
225  using Teuchos::Workspace;
227 
228  if(out)
229  *out << "\nUsing SuperLU to analyze and factor a new matrix ...\n";
230 
231  // Get the concrete factorization and nonzeros objects
232  FactorizationStructureSuperLU
233  &fs = dyn_cast<FactorizationStructureSuperLU>(*fact_struc);
234  FactorizationNonzerosSuperLU
235  &fn = dyn_cast<FactorizationNonzerosSuperLU>(*fact_nonzeros);
236 
237  // Allocate new storage if not done so already
238  if(!fs.fact_struct_.get())
239  fs.fact_struct_ = SuperLUPack::SuperLUSolver::create_fact_struct();
240  if(!fn.fact_nonzeros_.get())
241  fn.fact_nonzeros_ = SuperLUPack::SuperLUSolver::create_fact_nonzeros();
242 
243  // Get the dimensions of things.
244  const index_type
245  m = A.rows(),
246  n = A.cols(),
247  nz = A.num_nonzeros( MCTS::EXTRACT_FULL_MATRIX ,MCTS::ELEMENTS_ALLOW_DUPLICATES_SUM );
248 
249  // Validate input
251  n <= 0 || m <= 0 || m > n, std::invalid_argument
252  ,"DirectSparseSolverSuperLU::imp_analyze_and_factor(...) : Error!" );
253 
254  // Extract the matrix in coordinate format
255  Workspace<value_type> a_val(wss,nz);
256  Workspace<index_type> a_row_i(wss,nz);
257  Workspace<index_type> a_col_j(wss,nz);
259  MCTS::EXTRACT_FULL_MATRIX
260  ,MCTS::ELEMENTS_ALLOW_DUPLICATES_SUM
261  ,nz
262  ,&a_val[0]
263  ,nz
264  ,&a_row_i[0]
265  ,&a_col_j[0]
266  );
267 
268  //
269  // Convert to compressed sparse row format (which is compressed sparse
270  // column of the transposed matrix which will be passed to
271  // SuperLU for factorization).
272  //
273 
274  Workspace<double> acsr_val(wss,nz);
275  Workspace<int> acsr_col_j(wss,nz); // Zero-based for SuperLU
276  Workspace<int> acsr_row_ptr(wss,m+1);
277 
278  convet_to_csr(
279  n,m,nz,&a_val[0],&a_row_i[0],&a_col_j[0]
280  ,&acsr_val[0],&acsr_col_j[0],&acsr_row_ptr[0]
281  );
282 
283  //
284  // Have SuperLU factor this matrix.
285  //
286  // SuperLU works with the transpose of the matrix
287  // That DirectSparseSolver works with.
288  //
289 
290  Workspace<int> perm_r(wss,m); // Zero-based for SuperLU
291  Workspace<int> perm_c(wss,n); // Zero-based for SuperLU
292  int slu_rank = 0;
293 
294  fs.superlu_solver_->analyze_and_factor(
295  n // m
296  ,m // n
297  ,nz // nz
298  ,&acsr_val[0] // a_val[]
299  ,&acsr_col_j[0] // a_row_i[]
300  ,&acsr_row_ptr[0] // a_col_ptr[]
301  ,fs.fact_struct_.get() // fact_struct
302  ,fn.fact_nonzeros_.get() // fact_nonzeros
303  ,&perm_c[0] // perm_r[]
304  ,&perm_r[0] // perm_c[]
305  ,&slu_rank // rank
306  );
307 
308  // Copy the data to the output
309  row_perm->resize(m);
310  for( int i = 0; i < m; ++i )
311  (*row_perm)[i] = perm_r[i] + 1; // Convert from zero based to one based
312  col_perm->resize(n);
313  for( int j = 0; j < n; ++j )
314  (*col_perm)[j] = perm_c[j] + 1; // Convert from zero based to one based
315  *rank = slu_rank;
316 
317  // Sort partitions into assending order (required!)
318  std::sort(&(*row_perm)[0] , &(*row_perm)[0] + (*rank) );
319  std::sort(&(*col_perm)[0] , &(*col_perm)[0] + (*rank) );
320  if( *rank < m )
321  std::sort(&(*row_perm)[0] + (*rank) , &(*row_perm)[0] + m );
322  if( *rank < n )
323  std::sort(&(*col_perm)[0] + (*rank) , &(*col_perm)[0] + n );
324 
325 }
326 
327 void DirectSparseSolverSuperLU::imp_factor(
329  ,const FactorizationStructure &fact_struc
330  ,FactorizationNonzeros *fact_nonzeros
331  ,std::ostream *out
332  )
333 {
334  namespace mmp = MemMngPack;
335  using Teuchos::dyn_cast;
336  typedef MatrixConvertToSparse MCTS;
337  using Teuchos::Workspace;
339 
340  if(out)
341  *out << "\nUsing SuperLU to refactor the basis matrix ...\n";
342 
343  // Get the concrete factorization and nonzeros objects
344  const FactorizationStructureSuperLU
345  &fs = dyn_cast<const FactorizationStructureSuperLU>(fact_struc);
346  FactorizationNonzerosSuperLU
347  &fn = dyn_cast<FactorizationNonzerosSuperLU>(*fact_nonzeros);
348 
349  // Allocate new storage if not done so already
351  !fs.fact_struct_.get(), std::logic_error
352  ,"DirectSparseSolverSuperLU::imp_factor(...): Error, the factorization sturcture must "
353  "have already been computed!"
354  );
355  if(!fn.fact_nonzeros_.get())
356  fn.fact_nonzeros_ = SuperLUPack::SuperLUSolver::create_fact_nonzeros();
357 
358  // Get the dimensions of things.
359  const index_type
360  m = A.rows(),
361  n = A.cols(),
362  nz = A.num_nonzeros( MCTS::EXTRACT_FULL_MATRIX ,MCTS::ELEMENTS_ALLOW_DUPLICATES_SUM );
363 
364  // Validate input
366  n <= 0 || m <= 0 || m > n, std::invalid_argument
367  ,"DirectSparseSolverSuperLU::imp_factor(...) : Error!" );
368 
369  // Extract the matrix in coordinate format
370  Workspace<value_type> a_val(wss,nz);
371  Workspace<index_type> a_row_i(wss,nz);
372  Workspace<index_type> a_col_j(wss,nz);
374  MCTS::EXTRACT_FULL_MATRIX
375  ,MCTS::ELEMENTS_ALLOW_DUPLICATES_SUM
376  ,nz
377  ,&a_val[0]
378  ,nz
379  ,&a_row_i[0]
380  ,&a_col_j[0]
381  );
382 
383  //
384  // Convert to compressed sparse row format (which is compressed sparse
385  // column of the transposed matrix which will be passed to
386  // SuperLU for factorization).
387  //
388 
389  Workspace<double> acsr_val(wss,nz);
390  Workspace<int> acsr_col_j(wss,nz); // Zero-based for SuperLU
391  Workspace<int> acsr_row_ptr(wss,m+1);
392 
393  convet_to_csr(
394  n,m,nz,&a_val[0],&a_row_i[0],&a_col_j[0]
395  ,&acsr_val[0],&acsr_col_j[0],&acsr_row_ptr[0]
396  );
397 
398  //
399  // Have SuperLU factor this matrix.
400  //
401  // SuperLU works with the transpose of the matrix
402  // That DirectSparseSolver works with.
403  //
404 
405  fs.superlu_solver_->factor(
406  n // m
407  ,m // n
408  ,nz // nz
409  ,&acsr_val[0] // a_val[]
410  ,&acsr_col_j[0] // a_row_i[]
411  ,&acsr_row_ptr[0] // a_col_ptr[]
412  ,*fs.fact_struct_ // fact_struct
413  ,fn.fact_nonzeros_.get() // fact_nonzeros
414  );
415 
416 }
417 
418 // private
419 
420 } // end namespace AbstractLinAlgPack
421 
422 #endif // SPARSE_SOLVER_PACK_USE_SUPERLU
Teuchos::RCP< const Teuchos::AbstractFactory< BasisMatrix > > basis_matrix_factory_ptr_t
virtual void coor_extract_nonzeros(EExtractRegion extract_region, EElementUniqueness element_uniqueness, const index_type len_Aval, value_type Aval[], const index_type len_Aij, index_type Arow[], index_type Acol[], const index_type row_offset=0, const index_type col_offset=0) const =0
Extract sparse elements in a coordinate data structure.
Teuchos::Ordinal index_type
Typedef for the index type of elements that are used by the library.
virtual index_type num_nonzeros(EExtractRegion extract_region, EElementUniqueness element_uniqueness) const =0
Returns the number of nonzeros in the matrix.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Not transposed.
virtual size_type cols() const
Return the number of columns in the matrix.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
T_To & dyn_cast(T_From &from)
Mix-in interface for extracing explicit elements from a sparse matrix in one of several Fortran compa...
std::ostream * out
void V_InvMtV(VectorMutable *v_lhs, const MatrixNonsing &M_rhs1, BLAS_Cpp::Transp trans_rhs1, const Vector &v_rhs2)
v_lhs = inv(op(M_rhs1)) * v_rhs2
FortranTypes::f_dbl_prec value_type
Typedef for the value type of elements that is used for the library.
virtual size_type rows() const
Return the number of rows in the matrix.
Transp
TRANS.
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
TEUCHOSCORE_LIB_DLL_EXPORT Teuchos::RCP< WorkspaceStore > get_default_workspace_store()