|
Intrepid
|
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
1.7.6.1