1 // @HEADER
2 // ***********************************************************************
3 //
4 // Teuchos: Common Tools Package
5 // Copyright (2004) 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 Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41
42 #ifndef _TEUCHOS_SERIALDENSEHELPERS_HPP_
43 #define _TEUCHOS_SERIALDENSEHELPERS_HPP_
44
45 /*! \file Teuchos_SerialDenseHelpers.hpp
46 \brief Non-member helper functions on the templated serial, dense matrix/vector classes.
47 */
48
49 #include "Teuchos_ScalarTraits.hpp"
50 #include "Teuchos_DataAccess.hpp"
51 #include "Teuchos_ConfigDefs.hpp"
52 #include "Teuchos_Assert.hpp"
53 #include "Teuchos_SerialDenseMatrix.hpp"
54 #include "Teuchos_SerialSymDenseMatrix.hpp"
55 #include "Teuchos_SerialBandDenseMatrix.hpp"
56 #include "Teuchos_SerialDenseVector.hpp"
57
58 #include "Teuchos_CommHelpers.hpp"
59 #include "Teuchos_DefaultComm.hpp"
60
61 namespace Teuchos {
62
63 /*! \relates SerialSymDenseMatrix
64 \brief A templated, non-member, helper function for computing the matrix triple-product: B = alpha*W^T*A*W or B = alpha*W*A*W^T.
65
66 \param transw - [in] Compute B = alpha*W^T*A*W if transw = Teuchos::TRANS, else compute B = alpha*W*A*W^T if transw = Teuchos::NO_TRANS.
67 \param alpha - [in] The scaling factor.
68 \param A - [in] SerialSymDenseMatrix
69 \param W - [in] SerialDenseMatrix
70 \param B - [out] SerialSymDenseMatrix
71
72 \note The syntax for calling this function is: <tt> Teuchos::symMatTripleProduct<int,double>( Teuchos::TRANS, alpha, A, W, B ) </tt>
73 */
74 template<typename OrdinalType, typename ScalarType>
symMatTripleProduct(ETransp transw,const ScalarType alpha,const SerialSymDenseMatrix<OrdinalType,ScalarType> & A,const SerialDenseMatrix<OrdinalType,ScalarType> & W,SerialSymDenseMatrix<OrdinalType,ScalarType> & B)75 void symMatTripleProduct( ETransp transw, const ScalarType alpha, const SerialSymDenseMatrix<OrdinalType, ScalarType>& A,
76 const SerialDenseMatrix<OrdinalType, ScalarType>& W, SerialSymDenseMatrix<OrdinalType, ScalarType>& B )
77 {
78 // Local variables.
79 // Note: dimemensions of W are obtained so we can compute W^T*A*W for either cases.
80 OrdinalType A_nrowcols = A.numRows(); // A is a symmetric matrix and is assumed square.
81 OrdinalType B_nrowcols = (ETranspChar[transw]!='N') ? W.numCols() : W.numRows();
82 OrdinalType W_nrows = (ETranspChar[transw]!='N') ? W.numRows() : W.numCols();
83 OrdinalType W_ncols = (ETranspChar[transw]!='N') ? W.numCols() : W.numRows();
84
85 bool isBUpper = B.upper();
86
87 // Check for consistent dimensions.
88 TEUCHOS_TEST_FOR_EXCEPTION( B_nrowcols != B.numRows(), std::out_of_range,
89 "Teuchos::symMatTripleProduct<>() : "
90 "Num Rows/Cols B (" << B.numRows() << ") inconsistent with W ("<< B_nrowcols << ")");
91 TEUCHOS_TEST_FOR_EXCEPTION( A_nrowcols != W_nrows, std::out_of_range,
92 "Teuchos::symMatTripleProduct<>() : "
93 "Num Rows/Cols A (" << A_nrowcols << ") inconsistent with W ("<< W_nrows << ")");
94
95 // Scale by zero, initialized B to zeros and return.
96 if ( alpha == ScalarTraits<ScalarType>::zero() )
97 {
98 B.putScalar();
99 return;
100 }
101
102 // Workspace.
103 SerialDenseMatrix<OrdinalType, ScalarType> AW;
104
105 // BLAS class.
106 BLAS<OrdinalType, ScalarType> blas;
107 ScalarType one = Teuchos::ScalarTraits<ScalarType>::one();
108 ScalarType zero = Teuchos::ScalarTraits<ScalarType>::zero();
109
110 // Separate two cases because BLAS only supports symmetric matrix-matrix multply w/o transposes.
111 if (ETranspChar[transw]!='N') {
112 // Size AW to compute A*W
113 AW.shapeUninitialized(A_nrowcols,W_ncols);
114
115 // A*W
116 AW.multiply( Teuchos::LEFT_SIDE, alpha, A, W, ScalarTraits<ScalarType>::zero() );
117
118 // B = W^T*A*W
119 if (isBUpper) {
120 for (OrdinalType j=0; j<B_nrowcols; ++j)
121 blas.GEMV( transw, W_nrows, j+1, one, W.values(), W.stride(), AW[j], 1, zero, &B(0,j), 1 );
122 }
123 else {
124 for (OrdinalType j=0; j<B_nrowcols; ++j)
125 blas.GEMV( transw, W_nrows, B_nrowcols-j, one, W[j], W.stride(), AW[j], 1, zero, &B(j,j), 1 );
126 }
127 }
128 else {
129 // Size AW to compute W*A
130 AW.shapeUninitialized(W_ncols, A_nrowcols);
131
132 // W*A
133 AW.multiply( Teuchos::RIGHT_SIDE, alpha, A, W, ScalarTraits<ScalarType>::zero() );
134
135 // B = W*A*W^T
136 if (isBUpper) {
137 for (OrdinalType j=0; j<B_nrowcols; ++j)
138 for (OrdinalType i=0; i<=j; ++i)
139 blas.GEMV( transw, 1, A_nrowcols, one, &AW(i,0), AW.stride(), &W(j,0), W.stride(), zero, &B(i,j), 1 );
140 }
141 else {
142 for (OrdinalType j=0; j<B_nrowcols; ++j)
143 for (OrdinalType i=j; i<B_nrowcols; ++i)
144 blas.GEMV( transw, 1, A_nrowcols, one, &AW(i,0), AW.stride(), &W(j,0), W.stride(), zero, &B(i,j), 1 );
145 }
146 }
147
148 return;
149 }
150
151 /*! \relates SerialDenseMatrix
152 \brief A templated, non-member, helper function for viewing or copying a column of a SerialDenseMatrix as a SerialDenseVector.
153
154 \param CV - [in] Enumerated type set to Teuchos::Copy or Teuchos::View
155 \param A - [in] SerialDenseMatrix
156 \param col - [in] Integer indicating which column of A to return
157
158 \note The syntax for calling this function is: <tt>Teuchos::SerialDenseVector<int,double> col_j = Teuchos::getCol<int,double>( Teuchos::View, A, j )</tt>
159 */
160 template<typename OrdinalType, typename ScalarType>
161 SerialDenseVector<OrdinalType,ScalarType>
getCol(DataAccess CV,SerialDenseMatrix<OrdinalType,ScalarType> & A,const OrdinalType col)162 getCol( DataAccess CV, SerialDenseMatrix<OrdinalType, ScalarType>& A, const OrdinalType col )
163 {
164 return SerialDenseVector<OrdinalType, ScalarType>(CV, A[col], A.numRows());
165 }
166
167 /*! \relates SerialDenseMatrix
168 \brief A templated, non-member, helper function for setting a SerialDenseMatrix column using a SerialDenseVector.
169
170 \param v - [in] SerialDenseVector
171 \param col - [in] Integer indicating which column of A to replace with v
172 \param A - [out] SerialDenseMatrix
173
174 \note The syntax for calling this function is: bool err = Teuchos::setCol<int,double>( v, j, A )</tt>
175 */
176 template<typename OrdinalType, typename ScalarType>
setCol(const SerialDenseVector<OrdinalType,ScalarType> & v,const OrdinalType col,SerialDenseMatrix<OrdinalType,ScalarType> & A)177 bool setCol( const SerialDenseVector<OrdinalType, ScalarType>& v,
178 const OrdinalType col,
179 SerialDenseMatrix<OrdinalType, ScalarType>& A )
180 {
181 if (v.length() != A.numRows()) return false;
182
183 std::copy(v.values(),v.values()+v.length(),A[col]);
184
185 return true;
186 }
187
188 /*! \related SerialDenseMatrix
189 \brief A templated, non-member, helper function for generating a random SerialDenseMatrix that is synchronized in parallel.
190
191 \param A - [in/out] SerialDenseMatrix to be filled with random numbers that are the same across processors
192 */
193 template <typename OrdinalType, typename ScalarType>
randomSyncedMatrix(Teuchos::SerialDenseMatrix<OrdinalType,ScalarType> & A)194 void randomSyncedMatrix( Teuchos::SerialDenseMatrix<OrdinalType, ScalarType>& A )
195 {
196 Teuchos::RCP<const Teuchos::Comm<OrdinalType> >
197 comm = Teuchos::DefaultComm<OrdinalType>::getComm();
198
199 const OrdinalType procRank = rank(*comm);
200
201 // Construct a separate serial dense matrix and synchronize it to get around
202 // input matrices that are subviews of a larger matrix.
203 Teuchos::SerialDenseMatrix<OrdinalType, ScalarType> newMatrix( A.numRows(), A.numCols() );
204 if (procRank == 0)
205 newMatrix.random();
206 else
207 newMatrix.putScalar( Teuchos::ScalarTraits<ScalarType>::zero() );
208
209 broadcast(*comm, 0, A.numRows()*A.numCols(), newMatrix.values());
210
211 // Assign the synchronized matrix to the input.
212 A.assign( newMatrix );
213 }
214
215
216 /*! \relates SerialBandDenseMatrix
217 \brief A templated, non-member, helper function for converting a SerialDenseMatrix to a SerialBandDenseMatrix.
218
219 \param A - [in] SerialDenseMatrix to be converted
220 \param kl - [in] Integer indicating desired lower bandwidth of band matrix.
221 \param ku - [in] Integer indicating desired upper bandwidth of band matrix.
222 \param factorFormat - [in] Bool indicating whether kl extra superdiagonals should be stored to be used by factorization.
223
224 \note The syntax for calling this function is: <tt>Teuchos::SerialBandDenseMatrix<int,double> AB = Teuchos::generalToBanded<int,double>( A, kl, ku, true )</tt>
225 */
226 template<typename OrdinalType, typename ScalarType>
227 Teuchos::RCP<SerialBandDenseMatrix<OrdinalType, ScalarType> >
generalToBanded(const RCP<SerialDenseMatrix<OrdinalType,ScalarType>> & A,const OrdinalType kl,const OrdinalType ku,const bool factorFormat)228 generalToBanded(const RCP<SerialDenseMatrix<OrdinalType,ScalarType> >& A,
229 const OrdinalType kl, const OrdinalType ku,
230 const bool factorFormat)
231 {
232 OrdinalType m = A->numRows();
233 OrdinalType n = A->numCols();
234
235 // Check that the new matrix is consistent.
236 TEUCHOS_TEST_FOR_EXCEPTION(A->values()==0, std::invalid_argument,
237 "SerialBandDenseSolver<T>::generalToBanded: A is an empty SerialDenseMatrix<T>!");
238 TEUCHOS_TEST_FOR_EXCEPTION(kl<0 || kl>m, std::invalid_argument,
239 "SerialBandDenseSolver<T>::generalToBanded: The lower bandwidth kl is invalid!");
240 TEUCHOS_TEST_FOR_EXCEPTION(ku<0 || ku>n, std::invalid_argument,
241 "SerialBandDenseSolver<T>::generalToBanded: The upper bandwidth ku is invalid!");
242
243 OrdinalType extraBands = (factorFormat ? kl : 0);
244 Teuchos::RCP<SerialBandDenseMatrix<OrdinalType, ScalarType> > AB =
245 rcp( new SerialBandDenseMatrix<OrdinalType,ScalarType>(m,n,kl,extraBands+ku,true));
246
247 for (OrdinalType j = 0; j < n; j++) {
248 for (OrdinalType i=TEUCHOS_MAX(0,j-ku); i<=TEUCHOS_MIN(m-1,j+kl); i++) {
249 (*AB)(i,j) = (*A)(i,j);
250 }
251 }
252 return(AB);
253 }
254
255 /*! \relates SerialBandDenseMatrix
256 \brief A templated, non-member, helper function for converting a SerialBandDenseMatrix to a SerialDenseMatrix.
257
258 \param A - [in] SerialBandDenseMatrix to be converted
259
260 \note The syntax for calling this function is: <tt>Teuchos::SerialDenseMatrix<int,double> A = Teuchos::bandedToGeneral<int,double>( AB )</tt>
261 */
262 template<typename OrdinalType, typename ScalarType>
263 Teuchos::RCP<SerialDenseMatrix<OrdinalType, ScalarType> >
bandedToGeneral(const RCP<SerialBandDenseMatrix<OrdinalType,ScalarType>> & AB)264 bandedToGeneral(const RCP<SerialBandDenseMatrix<OrdinalType,ScalarType> >& AB)
265 {
266
267 OrdinalType m = AB->numRows();
268 OrdinalType n = AB->numCols();
269 OrdinalType kl = AB->lowerBandwidth();
270 OrdinalType ku = AB->upperBandwidth();
271
272 // Check that the new matrix is consistent.
273 TEUCHOS_TEST_FOR_EXCEPTION(AB->values()==0, std::invalid_argument,
274 "SerialBandDenseSolver<T>::bandedToGeneral: AB is an empty SerialBandDenseMatrix<T>!");
275
276 Teuchos::RCP<SerialDenseMatrix<OrdinalType, ScalarType> > A = rcp( new SerialDenseMatrix<OrdinalType,ScalarType>(m,n) );
277 for (OrdinalType j = 0; j < n; j++) {
278 for (OrdinalType i=TEUCHOS_MAX(0,j-ku); i<=TEUCHOS_MIN(m-1,j+kl); i++) {
279 (*A)(i,j) = (*AB)(i,j);
280 }
281 }
282 return(A);
283 }
284
285 } // namespace Teuchos
286
287 #endif /* _TEUCHOS_SERIALDENSEHELPERS_HPP_ */
288