AbstractLinAlgPack: C++ Interfaces For Vectors, Matrices And Related Linear Algebra Objects  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
AbstractLinAlgPack_BasisSystemPermDirectSparse.cpp
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 #include "AbstractLinAlgPack_BasisSystemPermDirectSparse.hpp"
43 #include "AbstractLinAlgPack_MatrixOp.hpp"
44 #include "AbstractLinAlgPack_MatrixOpNonsingAggr.hpp"
45 #include "AbstractLinAlgPack_MatrixPermAggr.hpp"
46 #include "AbstractLinAlgPack_MatrixConvertToSparseEncap.hpp"
47 #include "AbstractLinAlgPack_MatrixExtractSparseElements.hpp"
48 #include "AbstractLinAlgPack_MultiVectorMutableDense.hpp"
49 #include "AbstractLinAlgPack_PermutationSerial.hpp"
50 #include "AbstractLinAlgPack_MatrixSymPosDefCholFactor.hpp"
51 #include "Teuchos_AbstractFactoryStd.hpp"
52 #include "Teuchos_Assert.hpp"
53 #include "Teuchos_dyn_cast.hpp"
54 
55 namespace AbstractLinAlgPack {
56 
58  const direct_solver_ptr_t& direct_solver
59  )
61  Teuchos::rcp(
62  new Teuchos::AbstractFactoryStd<MatrixSymOp,MatrixSymPosDefCholFactor>()) // D'*D
63  ,Teuchos::rcp(
64  new Teuchos::AbstractFactoryStd<MatrixSymOpNonsing,MatrixSymPosDefCholFactor>()) // S
65  )
66 {
67  this->initialize(direct_solver);
68 }
69 
71  const direct_solver_ptr_t& direct_solver
72  )
73 {
74  direct_solver_ = direct_solver;
75  n_ = m_ = r_ = Gc_nz_ = 0;
76  init_var_inv_perm_.resize(0);
77  init_equ_inv_perm_.resize(0);
78  init_var_rng_ = Range1D::Invalid;
79  init_equ_rng_ = Range1D::Invalid;
80  var_dep_ = Range1D::Invalid;
81  var_indep_ = Range1D::Invalid;
82  equ_decomp_ = Range1D::Invalid;
83  equ_undecomp_ = Range1D::Invalid;
84 }
85 
86 // Overridden from BasisSystem
87 
90 {
91  return Teuchos::rcp(
93  );
94 }
95 
98 {
99  return Teuchos::rcp(
101  );
102 }
103 
106 {
107  return Teuchos::rcp(
109  );
110 }
111 
113 {
114  return var_dep_;
115 }
116 
118 {
119  return var_indep_;
120 }
121 
123 {
124  return equ_decomp_;
125 }
126 
128 {
129  return equ_undecomp_;
130 }
131 
133  const MatrixOp &Gc
134  ,MatrixOpNonsing *C
135  ,MatrixOp *D
136  ,MatrixOp *GcUP
137  ,EMatRelations mat_rel
138  ,std::ostream *out
139  ) const
140 {
141  using Teuchos::dyn_cast;
142  if(out)
143  *out << "\nUsing a direct sparse solver to update basis ...\n";
144  const size_type
145  n = Gc.rows(),
146  m = Gc.cols();
147 #ifdef TEUCHOS_DEBUG
148  const size_type Gc_rows = n, Gc_cols = m, Gc_nz = Gc.nz();
150  Gc_rows != n_ || Gc_cols != m_ || Gc_nz != Gc_nz_, std::invalid_argument
151  ,"BasisSystemPermDirectSparse::set_basis(...) : Error, "
152  "This matrix object is not compatible with last call to set_basis() or select_basis()!" );
154  C == NULL, std::invalid_argument
155  ,"BasisSystemPermDirectSparse::set_basis(...) : Error!" );
156 #endif
157  // Get the aggregate matrix object for Gc
158  const MatrixPermAggr
159  &Gc_pa = dyn_cast<const MatrixPermAggr>(Gc);
160  // Get the basis matrix object from the aggregate or allocate one
162  &C_aggr = dyn_cast<MatrixOpNonsingAggr>(*C);
164  C_bm = get_basis_matrix(C_aggr);
165  // Setup the encapulated convert-to-sparse matrix object
167  set_A_mctse( n, m, Gc_pa, &A_mctse );
168  // Refactor this basis (it had better be full rank)!
169  try {
170  direct_solver_->factor(
171  A_mctse
172  ,C_bm.get()
173  ,Teuchos::null // Same factorization structure as before
174  ,out
175  );
176  }
177  catch(const DirectSparseSolver::FactorizationFailure& excpt) {
178  if(out)
179  *out << "\nCurrent basis is singular : " << excpt.what() << std::endl
180  << "Throwing SingularBasis exception to client ...\n";
182  true, SingularBasis
183  ,"BasisSystemPermDirectSparse::update_basis(...) : Error, the current basis "
184  "is singular : " << excpt.what() );
185  }
186  // Update the aggregate basis matrix and compute the auxiliary projected matrices
187  update_basis_and_auxiliary_matrices( Gc, C_bm, &C_aggr, D, GcUP );
188 }
189 
190 // Overridded from BasisSystemPerm
191 
194 {
195  TEUCHOS_TEST_FOR_EXCEPT(true); // ToDo: Implement using PermutationSerial
196  return Teuchos::null;
197 }
198 
201 {
202  TEUCHOS_TEST_FOR_EXCEPT(true); // ToDo: Implement using PermutationSerial
203  return Teuchos::null;
204 }
205 
208 {
209  TEUCHOS_TEST_FOR_EXCEPT(true); // ToDo: Implement using PermutationSerial
210  return Teuchos::null;
211 }
212 
214  const Permutation &P_var
215  ,const Range1D &var_dep
216  ,const Permutation *P_equ
217  ,const Range1D *equ_decomp
218  ,const MatrixOp &Gc
219  ,MatrixOpNonsing *C
220  ,MatrixOp *D
221  ,MatrixOp *GcUP
222  ,EMatRelations mat_rel
223  ,std::ostream *out
224  )
225 {
226  using Teuchos::dyn_cast;
227  if(out)
228  *out << "\nUsing a direct sparse solver to set a new basis ...\n";
229  const size_type
230  n = Gc.rows(),
231  m = Gc.cols();
232 #ifdef TEUCHOS_DEBUG
233  const size_type Gc_rows = n, Gc_cols = m, Gc_nz = Gc.nz();
235  P_equ == NULL || equ_decomp == NULL, std::invalid_argument
236  ,"BasisSystemPermDirectSparse::set_basis(...) : Error!" );
238  C == NULL, std::invalid_argument
239  ,"BasisSystemPermDirectSparse::set_basis(...) : Error!" );
240 #endif
241  // Get the aggreate matrix object for Gc
242  const MatrixPermAggr
243  &Gc_pa = dyn_cast<const MatrixPermAggr>(Gc);
244  // Get the basis matrix object from the aggregate or allocate one
246  &C_aggr = dyn_cast<MatrixOpNonsingAggr>(*C);
248  C_bm = get_basis_matrix(C_aggr);
249  // Get at the concreate permutation vectors
250  const PermutationSerial
251  &P_var_s = dyn_cast<const PermutationSerial>(P_var),
252  &P_equ_s = dyn_cast<const PermutationSerial>(*P_equ);
253  // Setup the encapulated convert-to-sparse matrix object
254  init_var_inv_perm_ = *P_var_s.inv_perm();
255  init_var_rng_ = var_dep;
256  init_equ_inv_perm_ = *P_equ_s.inv_perm();
257  init_equ_rng_ = *equ_decomp;
259  set_A_mctse( n, m, Gc_pa, &A_mctse );
260  // Analyze and factor this basis (it had better be full rank)!
261  IVector row_perm_ds, col_perm_ds; // Must store these even though we don't want them!
262  size_type rank = 0;
263  direct_solver_->analyze_and_factor(
264  A_mctse
265  ,&row_perm_ds
266  ,&col_perm_ds
267  ,&rank
268  ,C_bm.get()
269  ,out
270  );
271  if( rank < var_dep.size() ) {
272  TEUCHOS_TEST_FOR_EXCEPT(true); // ToDo: Throw an exception with a good error message!
273  }
274  // Update the rest of the basis stuff
275  do_some_basis_stuff(Gc,var_dep,*equ_decomp,C_bm,&C_aggr,D,GcUP);
276 }
277 
279  const Vector *nu
280  ,MatrixOp *Gc
281  ,Permutation *P_var
282  ,Range1D *var_dep
283  ,Permutation *P_equ
284  ,Range1D *equ_decomp
285  ,MatrixOpNonsing *C
286  ,MatrixOp *D
287  ,MatrixOp *GcUP
288  ,EMatRelations mat_rel
289  ,std::ostream *out
290  )
291 {
292  using Teuchos::dyn_cast;
293  if(out)
294  *out << "\nUsing a direct sparse solver to select a new basis ...\n";
295 #ifdef TEUCHOS_DEBUG
296  // Validate input
297  const char msg_err_head[] = "BasisSystemPermDirectSparse::set_basis(...) : Error!";
299  Gc == NULL, std::invalid_argument
300  ,msg_err_head << " Must have equality constriants in this current implementation! " );
301 #endif
302  const size_type
303  n = Gc->rows(),
304  m = Gc->cols();
305 #ifdef TEUCHOS_DEBUG
306  // Validate input
307  const size_type Gc_rows = Gc->rows(), Gc_cols = Gc->cols(), Gc_nz = Gc->nz();
309  P_var == NULL || var_dep == NULL, std::invalid_argument, msg_err_head );
311  P_equ == NULL || equ_decomp == NULL, std::invalid_argument, msg_err_head );
313  C == NULL, std::invalid_argument, msg_err_head );
314 #endif
315  // Get the aggreate matrix object for Gc
317  &Gc_pa = dyn_cast<MatrixPermAggr>(*Gc);
318  // Get the basis matrix object from the aggregate or allocate one
320  &C_aggr = dyn_cast<MatrixOpNonsingAggr>(*C);
322  C_bm = get_basis_matrix(C_aggr);
323  // Setup the encapulated convert-to-sparse matrix object
324  // ToDo: Use nu to exclude variables that are at a bound!
325  init_var_rng_ = Range1D(1,n);
326  init_var_inv_perm_.resize(0); // Not used since above is full range
327  init_equ_rng_ = Range1D(1,m);
328  init_equ_inv_perm_.resize(0); // Not used since above is full range
330  set_A_mctse( n, m, Gc_pa, &A_mctse );
331  // Analyze and factor this basis (it had better be full rank)!
333  var_perm_ds = Teuchos::rcp(new IVector),
334  equ_perm_ds = Teuchos::rcp(new IVector);
335  size_type rank = 0;
336  direct_solver_->analyze_and_factor(
337  A_mctse
338  ,equ_perm_ds.get()
339  ,var_perm_ds.get()
340  ,&rank
341  ,C_bm.get()
342  ,out
343  );
344  if( rank == 0 ) {
345  TEUCHOS_TEST_FOR_EXCEPT( !( rank == 0 ) ); // ToDo: Throw exception with good error message!
346  }
347  // Return the selected basis
348  // ToDo: Use var_perm_ds and equ_perm_ds together with nu to
349  // get the overall permuations for all of the variables.
350  PermutationSerial
351  &P_var_s = dyn_cast<PermutationSerial>(*P_var),
352  &P_equ_s = dyn_cast<PermutationSerial>(*P_equ);
353  // Create the overall permutations to set to the permutation matrices!
354  *var_dep = Range1D(1,rank);
355  P_var_s.initialize( var_perm_ds, Teuchos::null );
356  *equ_decomp = Range1D(1,rank);
357  P_equ_s.initialize( equ_perm_ds, Teuchos::null );
358  // Setup Gc_aggr with Gc_perm
359  const int num_row_part = 2;
360  const int num_col_part = 2;
361  const index_type row_part[3] = { 1, rank, n+1 };
362  const index_type col_part[3] = { 1, rank, m+1 };
363  Gc_pa.initialize(
364  Gc_pa.mat_orig()
365  ,Teuchos::rcp(new PermutationSerial(var_perm_ds,Teuchos::null)) // var_perm_ds reuse is okay!
366  ,Teuchos::rcp(new PermutationSerial(equ_perm_ds,Teuchos::null)) // equ_perm_ds resue is okay!
367  ,Gc_pa.mat_orig()->perm_view(
368  P_var,row_part,num_row_part
369  ,P_equ,col_part,num_col_part
370  )
371  );
372  // Update the rest of the basis stuff
373  do_some_basis_stuff(*Gc,*var_dep,*equ_decomp,C_bm,&C_aggr,D,GcUP);
374 }
375 
376 // private
377 
379 BasisSystemPermDirectSparse::get_basis_matrix( MatrixOpNonsingAggr &C_aggr ) const
380 {
381  using Teuchos::dyn_cast;
383  if( C_aggr.mns().get() ) {
384  C_bm = Teuchos::rcp_dynamic_cast<DirectSparseSolver::BasisMatrix>(
385  Teuchos::rcp_const_cast<MatrixNonsing>(C_aggr.mns() ) );
386  if(C_bm.get() == NULL)
387  dyn_cast<const DirectSparseSolver::BasisMatrix>(*C_aggr.mns()); // Throws exception!
388  }
389  else {
390  C_bm = direct_solver_->basis_matrix_factory()->create();
391  }
392  return C_bm;
393 }
394 
395 void BasisSystemPermDirectSparse::set_A_mctse(
396  size_type n
397  ,size_type m
398  ,const MatrixPermAggr &Gc_pa
399  ,MatrixConvertToSparseEncap *A_mctse
400  ) const
401 {
402  A_mctse->initialize(
403  Teuchos::rcp_dynamic_cast<const MatrixExtractSparseElements>(Gc_pa.mat_orig())
404  ,Teuchos::rcp( init_var_rng_.size() < n ? &init_var_inv_perm_ : NULL, false )
405  ,init_var_rng_
406  ,Teuchos::rcp( init_equ_rng_.size() < m ? &init_equ_inv_perm_ : NULL, false )
407  ,init_equ_rng_
409  );
410 }
411 
412 void BasisSystemPermDirectSparse::update_basis_and_auxiliary_matrices(
413  const MatrixOp& Gc
415  ,MatrixOpNonsingAggr *C_aggr
416  ,MatrixOp* D, MatrixOp* GcUP
417  ) const
418 {
419  using Teuchos::dyn_cast;
420  // Initialize the aggregate basis matrix object.
421  C_aggr->initialize(
422  Gc.sub_view(var_dep_,equ_decomp_)
424  ,C_bm
426  );
427  // Compute the auxiliary projected matrices
428  // Get the concreate type of the direct sensitivity matrix (if one was passed in)
429  if( D ) {
430  MultiVectorMutableDense *D_mvd = &dyn_cast<MultiVectorMutableDense>(*D);
431  TEUCHOS_TEST_FOR_EXCEPT( !( D ) ); // ToDo: Throw exception!
432  // D = -inv(C) * N
433  D_mvd->initialize(var_dep_.size(),var_indep_.size());
435  D_mvd, -1.0, *C_bm, BLAS_Cpp::no_trans
436  ,*Gc.sub_view(var_indep_,equ_decomp_),BLAS_Cpp::trans // N = Gc(var_indep,equ_decomp)'
437  );
438  }
439  if( GcUP ) {
440  TEUCHOS_TEST_FOR_EXCEPT(true); // ToDo: Implement!
441  }
442 }
443 
444 void BasisSystemPermDirectSparse::do_some_basis_stuff(
445  const MatrixOp& Gc
446  ,const Range1D& var_dep, const Range1D& equ_decomp
448  ,MatrixOpNonsingAggr *C_aggr
449  ,MatrixOp* D, MatrixOp* GcUP
450  )
451 {
452  const size_type
453  n = Gc.rows(),
454  m = Gc.cols();
455  // Set the ranges
456  var_dep_ = var_dep;
457  var_indep_ = ( var_dep.size() == n
459  : ( var_dep.lbound() == 1
460  ? Range1D(var_dep.size()+1,n)
461  : Range1D(1,n-var_dep.size()) ) );
462  equ_decomp_ = equ_decomp;
463  equ_undecomp_ = ( equ_decomp.size() == m
465  : ( equ_decomp.lbound() == 1
466  ? Range1D(equ_decomp.size()+1,m)
467  : Range1D(1,m-equ_decomp.size()) ) );
468  // Set the basis system dimensions
469  n_ = n;
470  m_ = m;
471  r_ = var_dep.size();
472  Gc_nz_ = Gc.nz();
473  // Update the aggregate basis matrix and compute the auxiliary projected matrices
474  update_basis_and_auxiliary_matrices( Gc, C_bm, C_aggr, D, GcUP );
475 }
476 
477 } // end namespace AbstractLinAlgPack
virtual size_type nz() const
Return the number of nonzero elements in the matrix.
Abstract interface for immutable, finite dimensional, coordinate vectors {abstract}.
Abstract base class for all polymorphic symmetrix nonsingular matrices that can be used to compute ma...
BasisSystemPermDirectSparse(const direct_solver_ptr_t &direct_solver=Teuchos::null)
Calls this->initialize()
void initialize(const direct_solver_ptr_t &direct_solver)
Initialize given a direct sparse solver object.
Abstract class for objects that represent the factorized matrix and can be used to solve for differen...
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Index size() const
Aggregate matrix class for a matrix and its permuted view.
T_To & dyn_cast(T_From &from)
T * get() const
virtual mat_ptr_t perm_view(const Permutation *P_row, const index_type row_part[], int num_row_part, const Permutation *P_col, const index_type col_part[], int num_col_part) const
Create a permuted view: M_perm = P_row' * M * P_col.
Interface adding operations specific for a symmetric matrix {abstract}.
void initialize(const mat_ptr_t &mat_orig, const perm_ptr_t &row_perm, const perm_ptr_t &col_perm, const mat_ptr_t &mat_perm)
Initialize.
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)
size_t size_type
Base class for all matrices that support basic matrix operations.
static const Range1D Invalid
Abstract interface to permutation matrices.
void set_basis(const Permutation &P_var, const Range1D &var_dep, const Permutation *P_equ, const Range1D *equ_decomp, const MatrixOp &Gc, MatrixOpNonsing *C, MatrixOp *D, MatrixOp *GcUP, EMatRelations mat_rel, std::ostream *out)
Interface for setting and selecting a basis from the Jacobian from a set of equations.
Abstract base class for all nonsingular polymorphic matrices that can be used to compute matrix-vecto...
void M_StInvMtM(MatrixOp *m_lhs, value_type alpha, const MatrixNonsing &M_rhs1, BLAS_Cpp::Transp trans_rhs1, const MatrixOp &mwo_rhs2, BLAS_Cpp::Transp trans_rhs2)
m_lhs = alpha * inv(op(mwo_rhs1)) * op(mwo_rhs2) (right)
virtual size_type rows() const
Return the number of rows in the matrix.
void select_basis(const Vector *nu, MatrixOp *Gc, Permutation *P_var, Range1D *var_dep, Permutation *P_equ, Range1D *equ_decomp, MatrixOpNonsing *C, MatrixOp *D, MatrixOp *GcUP, EMatRelations mat_rel, std::ostream *out)
Abstract base class for all nonsingular polymorphic matrices that can solve for linear system with bu...
Sparse conversion subclass based on views of a MatrixExtractSparseElements object.
void update_basis(const MatrixOp &Gc, MatrixOpNonsing *C, MatrixOp *D, MatrixOp *GcUP, EMatRelations mat_rel, std::ostream *out) const
Aggregate matrix class pulling together a MatrixOp object and a MatrixNonsing object into a unified m...
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)