Intrepid
/usr/src/RPM/BUILD/trilinos-11.12.1/packages/intrepid/src/Shared/MiniTensor/Intrepid_MiniTensor_LinearAlgebra.i.h
00001 // @HEADER
00002 // ************************************************************************
00003 //
00004 //                           Intrepid Package
00005 //                 Copyright (2007) Sandia Corporation
00006 //
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions: Alejandro Mota (amota@sandia.gov)
00038 //
00039 // ************************************************************************
00040 // @HEADER
00041 
00042 #if !defined(Intrepid_MiniTensor_LinearAlgebra_i_h)
00043 #define Intrepid_MiniTensor_LinearAlgebra_i_h
00044 
00045 namespace Intrepid {
00046 
00047 //
00048 // R^N tensor Frobenius norm
00049 // \return \f$ \sqrt{A:A} \f$
00050 //
00051 template<typename T, Index N>
00052 inline
00053 T
00054 norm(Tensor<T, N> const & A)
00055 {
00056   Index const
00057   dimension = A.get_dimension();
00058 
00059   T
00060   s = 0.0;
00061 
00062   switch (dimension) {
00063 
00064     default:
00065       s = norm_f_square(A);
00066       break;
00067 
00068     case 3:
00069       s+= A(0,0)*A(0,0) + A(0,1)*A(0,1) + A(0,2)*A(0,2);
00070       s+= A(1,0)*A(1,0) + A(1,1)*A(1,1) + A(1,2)*A(1,2);
00071       s+= A(2,0)*A(2,0) + A(2,1)*A(2,1) + A(2,2)*A(2,2);
00072       break;
00073 
00074     case 2:
00075       s+= A(0,0)*A(0,0) + A(0,1)*A(0,1);
00076       s+= A(1,0)*A(1,0) + A(1,1)*A(1,1);
00077       break;
00078 
00079   }
00080 
00081   if (s > 0.0) return std::sqrt(s);
00082 
00083   return 0.0;
00084 
00085 }
00086 
00087 //
00088 // R^N tensor 1-norm
00089 // \return \f$ \max_{j \in {0,\cdots,N}}\Sigma_{i=0}^N |A_{ij}| \f$
00090 //
00091 template<typename T, Index N>
00092 inline
00093 T
00094 norm_1(Tensor<T, N> const & A)
00095 {
00096   Index const
00097   dimension = A.get_dimension();
00098 
00099   Vector<T, N>
00100   v(dimension);
00101 
00102   T
00103   s = 0.0;
00104 
00105   switch (dimension) {
00106 
00107     default:
00108 
00109       for (Index i = 0; i < dimension; ++i) {
00110         T t = 0.0;
00111         for (Index j = 0; j < dimension; ++j) {
00112           t += std::abs(A(j, i));
00113         }
00114         v(i) = t;
00115       }
00116 
00117       for (Index i = 0; i < dimension; ++i) {
00118         s = std::max(s, v(i));
00119       }
00120       break;
00121 
00122     case 3:
00123       v(0) = std::abs(A(0,0)) + std::abs(A(1,0)) + std::abs(A(2,0));
00124       v(1) = std::abs(A(0,1)) + std::abs(A(1,1)) + std::abs(A(2,1));
00125       v(2) = std::abs(A(0,2)) + std::abs(A(1,2)) + std::abs(A(2,2));
00126 
00127       s = std::max(std::max(v(0),v(1)),v(2));
00128       break;
00129 
00130     case 2:
00131       v(0) = std::abs(A(0,0)) + std::abs(A(1,0));
00132       v(1) = std::abs(A(0,1)) + std::abs(A(1,1));
00133 
00134       s = std::max(v(0),v(1));
00135       break;
00136 
00137   }
00138 
00139   return s;
00140 }
00141 
00142 //
00143 // R^N tensor infinity-norm
00144 // \return \f$ \max_{i \in {0,\cdots,N}}\Sigma_{j=0}^N |A_{ij}| \f$
00145 //
00146 template<typename T, Index N>
00147 inline
00148 T
00149 norm_infinity(Tensor<T, N> const & A)
00150 {
00151   Index const
00152   dimension = A.get_dimension();
00153 
00154   Vector<T, N>
00155   v(dimension);
00156 
00157   T s = 0.0;
00158 
00159   switch (dimension) {
00160 
00161     default:
00162       for (Index i = 0; i < dimension; ++i) {
00163         T t = 0.0;
00164         for (Index j = 0; j < dimension; ++j) {
00165           t += std::abs(A(i, j));
00166         }
00167         v(i) = t;
00168       }
00169 
00170       for (Index i = 0; i < dimension; ++i) {
00171         s = std::max(s, v(i));
00172       }
00173       break;
00174 
00175     case 3:
00176       v(0) = std::abs(A(0,0)) + std::abs(A(0,1)) + std::abs(A(0,2));
00177       v(1) = std::abs(A(1,0)) + std::abs(A(1,1)) + std::abs(A(1,2));
00178       v(2) = std::abs(A(2,0)) + std::abs(A(2,1)) + std::abs(A(2,2));
00179 
00180       s = std::max(std::max(v(0),v(1)),v(2));
00181       break;
00182 
00183     case 2:
00184       v(0) = std::abs(A(0,0)) + std::abs(A(0,1));
00185       v(1) = std::abs(A(1,0)) + std::abs(A(1,1));
00186 
00187       s = std::max(v(0),v(1));
00188       break;
00189 
00190   }
00191 
00192   return s;
00193 }
00194 
00195 //
00196 // Swap row. Exchange rows i and j in place
00197 // \param A tensor
00198 // \param i index
00199 // \param j index
00200 //
00201 template<typename T, Index N>
00202 void
00203 swap_row(Tensor<T, N> & A, Index const i, Index const j)
00204 {
00205   Index const
00206   dimension = A.get_dimension();
00207 
00208   if (i != j) {
00209     for (Index k = 0; k < dimension; ++k) {
00210       std::swap(A(i, k), A(j, k));
00211     }
00212   }
00213   return;
00214 }
00215 
00216 //
00217 // Swap column. Exchange columns i and j in place
00218 // \param A tensor
00219 // \param i index
00220 // \param j index
00221 //
00222 template<typename T, Index N>
00223 void
00224 swap_col(Tensor<T, N> & A, Index const i, Index const j)
00225 {
00226   Index const
00227   dimension = A.get_dimension();
00228 
00229   if (i != j) {
00230     for (Index k = 0; k < dimension; ++k) {
00231       std::swap(A(k, i), A(k, j));
00232     }
00233   }
00234   return;
00235 }
00236 
00237 //
00238 // R^N determinant
00239 // Laplace expansion. Warning: no pivoting.
00240 // Casual use only. Use Teuchos LAPACK interface for
00241 // more efficient and robust techniques.
00242 // \param A tensor
00243 // \return \f$ \det A \f$
00244 //
00245 template<typename T, Index N>
00246 inline
00247 T
00248 det(Tensor<T, N> const & A)
00249 {
00250   Index const
00251   dimension = A.get_dimension();
00252 
00253   T
00254   s = 0.0;
00255 
00256   switch (dimension) {
00257 
00258     default:
00259     {
00260       int sign = 1;
00261       for (Index i = 0; i < dimension; ++i) {
00262         const T d = det(subtensor(A, i, 1));
00263         s += sign * d * A(i, 1);
00264         sign *= -1;
00265       }
00266     }
00267     break;
00268 
00269     case 3:
00270       s = -A(0,2)*A(1,1)*A(2,0) + A(0,1)*A(1,2)*A(2,0) +
00271            A(0,2)*A(1,0)*A(2,1) - A(0,0)*A(1,2)*A(2,1) -
00272            A(0,1)*A(1,0)*A(2,2) + A(0,0)*A(1,1)*A(2,2);
00273       break;
00274 
00275     case 2:
00276       s = A(0,0) * A(1,1) - A(1,0) * A(0,1);
00277       break;
00278 
00279   }
00280 
00281   return s;
00282 }
00283 
00284 //
00285 // R^N trace
00286 // \param A tensor
00287 // \return \f$ A:I \f$
00288 //
00289 template<typename T, Index N>
00290 inline
00291 T
00292 trace(Tensor<T, N> const & A)
00293 {
00294   Index const
00295   dimension = A.get_dimension();
00296 
00297   T s = 0.0;
00298 
00299   switch (dimension) {
00300 
00301     default:
00302       for (Index i = 0; i < dimension; ++i) {
00303         s += A(i,i);
00304       }
00305       break;
00306 
00307     case 3:
00308       s = A(0,0) + A(1,1) + A(2,2);
00309       break;
00310 
00311     case 2:
00312       s = A(0,0) + A(1,1);
00313       break;
00314 
00315   }
00316 
00317   return s;
00318 }
00319 
00320 //
00321 // R^N first invariant, trace
00322 // \param A tensor
00323 // \return \f$ I_A = A:I \f$
00324 //
00325 template<typename T, Index N>
00326 inline
00327 T
00328 I1(Tensor<T, N> const & A)
00329 {
00330   return trace(A);
00331 }
00332 
00333 //
00334 // R^N second invariant
00335 // \param A tensor
00336 // \return \f$ II_A = \frac{1}{2}((I_A)^2-I_{A^2}) \f$
00337 //
00338 template<typename T, Index N>
00339 inline
00340 T
00341 I2(Tensor<T, N> const & A)
00342 {
00343   Index const
00344   dimension = A.get_dimension();
00345 
00346   T
00347   s = 0.0;
00348 
00349   T const
00350   trA = trace(A);
00351 
00352   switch (dimension) {
00353 
00354     default:
00355       s = 0.5 * (trA * trA - trace(A * A));
00356       break;
00357 
00358     case 3:
00359       s = 0.5 * (trA*trA - A(0,0)*A(0,0) - A(1,1)*A(1,1) - A(2,2)*A(2,2)) -
00360       A(0,1)*A(1,0) - A(0,2)*A(2,0) - A(1,2)*A(2,1);
00361       break;
00362 
00363     case 2:
00364       s =  0.5 * (trA * trA - trace(A * A));
00365       break;
00366 
00367   }
00368 
00369   return s;
00370 }
00371 
00372 //
00373 // R^N third invariant
00374 // \param A tensor
00375 // \return \f$ III_A = \det A \f$
00376 //
00377 template<typename T, Index N>
00378 inline
00379 T
00380 I3(Tensor<T, N> const & A)
00381 {
00382   return det(A);
00383 }
00384 
00385 } // namespace Intrepid
00386 
00387 #endif // Intrepid_MiniTensor_LinearAlgebra_i_h